1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2016 6WIND S.A.
3 * Copyright 2016 Mellanox Technologies, Ltd
13 #include <arpa/inet.h>
14 #include <sys/socket.h>
16 #include <rte_common.h>
17 #include <rte_eth_ctrl.h>
18 #include <rte_ethdev.h>
19 #include <rte_byteorder.h>
20 #include <cmdline_parse.h>
21 #include <cmdline_parse_etheraddr.h>
26 /** Parser token indices. */
46 /* Top-level command. */
49 /* Sub-level commands. */
58 /* Destroy arguments. */
61 /* Query arguments. */
67 /* Validate/create arguments. */
74 /* Validate/create pattern. */
111 ITEM_VLAN_INNER_TYPE,
143 ITEM_E_TAG_GRP_ECID_B,
162 ITEM_ARP_ETH_IPV4_SHA,
163 ITEM_ARP_ETH_IPV4_SPA,
164 ITEM_ARP_ETH_IPV4_THA,
165 ITEM_ARP_ETH_IPV4_TPA,
167 ITEM_IPV6_EXT_NEXT_HDR,
172 ITEM_ICMP6_ND_NS_TARGET_ADDR,
174 ITEM_ICMP6_ND_NA_TARGET_ADDR,
176 ITEM_ICMP6_ND_OPT_TYPE,
177 ITEM_ICMP6_ND_OPT_SLA_ETH,
178 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
179 ITEM_ICMP6_ND_OPT_TLA_ETH,
180 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
184 /* Validate/create actions. */
204 ACTION_RSS_FUNC_DEFAULT,
205 ACTION_RSS_FUNC_TOEPLITZ,
206 ACTION_RSS_FUNC_SIMPLE_XOR,
218 ACTION_PHY_PORT_ORIGINAL,
219 ACTION_PHY_PORT_INDEX,
221 ACTION_PORT_ID_ORIGINAL,
225 ACTION_OF_SET_MPLS_TTL,
226 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
227 ACTION_OF_DEC_MPLS_TTL,
228 ACTION_OF_SET_NW_TTL,
229 ACTION_OF_SET_NW_TTL_NW_TTL,
230 ACTION_OF_DEC_NW_TTL,
231 ACTION_OF_COPY_TTL_OUT,
232 ACTION_OF_COPY_TTL_IN,
235 ACTION_OF_PUSH_VLAN_ETHERTYPE,
236 ACTION_OF_SET_VLAN_VID,
237 ACTION_OF_SET_VLAN_VID_VLAN_VID,
238 ACTION_OF_SET_VLAN_PCP,
239 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
241 ACTION_OF_POP_MPLS_ETHERTYPE,
243 ACTION_OF_PUSH_MPLS_ETHERTYPE,
250 ACTION_MPLSOUDP_ENCAP,
251 ACTION_MPLSOUDP_DECAP,
253 ACTION_SET_IPV4_SRC_IPV4_SRC,
255 ACTION_SET_IPV4_DST_IPV4_DST,
257 ACTION_SET_IPV6_SRC_IPV6_SRC,
259 ACTION_SET_IPV6_DST_IPV6_DST,
261 ACTION_SET_TP_SRC_TP_SRC,
263 ACTION_SET_TP_DST_TP_DST,
269 ACTION_SET_MAC_SRC_MAC_SRC,
271 ACTION_SET_MAC_DST_MAC_DST,
274 /** Maximum size for pattern in struct rte_flow_item_raw. */
275 #define ITEM_RAW_PATTERN_SIZE 40
277 /** Storage size for struct rte_flow_item_raw including pattern. */
278 #define ITEM_RAW_SIZE \
279 (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE)
281 /** Maximum number of queue indices in struct rte_flow_action_rss. */
282 #define ACTION_RSS_QUEUE_NUM 32
284 /** Storage for struct rte_flow_action_rss including external data. */
285 struct action_rss_data {
286 struct rte_flow_action_rss conf;
287 uint8_t key[RSS_HASH_KEY_LENGTH];
288 uint16_t queue[ACTION_RSS_QUEUE_NUM];
291 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */
292 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6
294 /** Storage for struct rte_flow_action_vxlan_encap including external data. */
295 struct action_vxlan_encap_data {
296 struct rte_flow_action_vxlan_encap conf;
297 struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
298 struct rte_flow_item_eth item_eth;
299 struct rte_flow_item_vlan item_vlan;
301 struct rte_flow_item_ipv4 item_ipv4;
302 struct rte_flow_item_ipv6 item_ipv6;
304 struct rte_flow_item_udp item_udp;
305 struct rte_flow_item_vxlan item_vxlan;
308 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */
309 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5
311 /** Storage for struct rte_flow_action_nvgre_encap including external data. */
312 struct action_nvgre_encap_data {
313 struct rte_flow_action_nvgre_encap conf;
314 struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM];
315 struct rte_flow_item_eth item_eth;
316 struct rte_flow_item_vlan item_vlan;
318 struct rte_flow_item_ipv4 item_ipv4;
319 struct rte_flow_item_ipv6 item_ipv6;
321 struct rte_flow_item_nvgre item_nvgre;
324 /** Maximum data size in struct rte_flow_action_raw_encap. */
325 #define ACTION_RAW_ENCAP_MAX_DATA 128
327 /** Storage for struct rte_flow_action_raw_encap including external data. */
328 struct action_raw_encap_data {
329 struct rte_flow_action_raw_encap conf;
330 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
331 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA];
334 /** Storage for struct rte_flow_action_raw_decap including external data. */
335 struct action_raw_decap_data {
336 struct rte_flow_action_raw_decap conf;
337 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA];
340 /** Maximum number of subsequent tokens and arguments on the stack. */
341 #define CTX_STACK_SIZE 16
343 /** Parser context. */
345 /** Stack of subsequent token lists to process. */
346 const enum index *next[CTX_STACK_SIZE];
347 /** Arguments for stacked tokens. */
348 const void *args[CTX_STACK_SIZE];
349 enum index curr; /**< Current token index. */
350 enum index prev; /**< Index of the last token seen. */
351 int next_num; /**< Number of entries in next[]. */
352 int args_num; /**< Number of entries in args[]. */
353 uint32_t eol:1; /**< EOL has been detected. */
354 uint32_t last:1; /**< No more arguments. */
355 portid_t port; /**< Current port ID (for completions). */
356 uint32_t objdata; /**< Object-specific data. */
357 void *object; /**< Address of current object for relative offsets. */
358 void *objmask; /**< Object a full mask must be written to. */
361 /** Token argument. */
363 uint32_t hton:1; /**< Use network byte ordering. */
364 uint32_t sign:1; /**< Value is signed. */
365 uint32_t bounded:1; /**< Value is bounded. */
366 uintmax_t min; /**< Minimum value if bounded. */
367 uintmax_t max; /**< Maximum value if bounded. */
368 uint32_t offset; /**< Relative offset from ctx->object. */
369 uint32_t size; /**< Field size. */
370 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
373 /** Parser token definition. */
375 /** Type displayed during completion (defaults to "TOKEN"). */
377 /** Help displayed during completion (defaults to token name). */
379 /** Private data used by parser functions. */
382 * Lists of subsequent tokens to push on the stack. Each call to the
383 * parser consumes the last entry of that stack.
385 const enum index *const *next;
386 /** Arguments stack for subsequent tokens that need them. */
387 const struct arg *const *args;
389 * Token-processing callback, returns -1 in case of error, the
390 * length of the matched string otherwise. If NULL, attempts to
391 * match the token name.
393 * If buf is not NULL, the result should be stored in it according
394 * to context. An error is returned if not large enough.
396 int (*call)(struct context *ctx, const struct token *token,
397 const char *str, unsigned int len,
398 void *buf, unsigned int size);
400 * Callback that provides possible values for this token, used for
401 * completion. Returns -1 in case of error, the number of possible
402 * values otherwise. If NULL, the token name is used.
404 * If buf is not NULL, entry index ent is written to buf and the
405 * full length of the entry is returned (same behavior as
408 int (*comp)(struct context *ctx, const struct token *token,
409 unsigned int ent, char *buf, unsigned int size);
410 /** Mandatory token name, no default value. */
414 /** Static initializer for the next field. */
415 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, }
417 /** Static initializer for a NEXT() entry. */
418 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, }
420 /** Static initializer for the args field. */
421 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, }
423 /** Static initializer for ARGS() to target a field. */
424 #define ARGS_ENTRY(s, f) \
425 (&(const struct arg){ \
426 .offset = offsetof(s, f), \
427 .size = sizeof(((s *)0)->f), \
430 /** Static initializer for ARGS() to target a bit-field. */
431 #define ARGS_ENTRY_BF(s, f, b) \
432 (&(const struct arg){ \
434 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \
437 /** Static initializer for ARGS() to target an arbitrary bit-mask. */
438 #define ARGS_ENTRY_MASK(s, f, m) \
439 (&(const struct arg){ \
440 .offset = offsetof(s, f), \
441 .size = sizeof(((s *)0)->f), \
442 .mask = (const void *)(m), \
445 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */
446 #define ARGS_ENTRY_MASK_HTON(s, f, m) \
447 (&(const struct arg){ \
449 .offset = offsetof(s, f), \
450 .size = sizeof(((s *)0)->f), \
451 .mask = (const void *)(m), \
454 /** Static initializer for ARGS() to target a pointer. */
455 #define ARGS_ENTRY_PTR(s, f) \
456 (&(const struct arg){ \
457 .size = sizeof(*((s *)0)->f), \
460 /** Static initializer for ARGS() with arbitrary offset and size. */
461 #define ARGS_ENTRY_ARB(o, s) \
462 (&(const struct arg){ \
467 /** Same as ARGS_ENTRY_ARB() with bounded values. */
468 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
469 (&(const struct arg){ \
477 /** Same as ARGS_ENTRY() using network byte ordering. */
478 #define ARGS_ENTRY_HTON(s, f) \
479 (&(const struct arg){ \
481 .offset = offsetof(s, f), \
482 .size = sizeof(((s *)0)->f), \
485 /** Parser output buffer layout expected by cmd_flow_parsed(). */
487 enum index command; /**< Flow command. */
488 portid_t port; /**< Affected port ID. */
491 struct rte_flow_attr attr;
492 struct rte_flow_item *pattern;
493 struct rte_flow_action *actions;
497 } vc; /**< Validate/create arguments. */
501 } destroy; /**< Destroy arguments. */
504 struct rte_flow_action action;
505 } query; /**< Query arguments. */
509 } list; /**< List arguments. */
512 } isolate; /**< Isolated mode arguments. */
513 } args; /**< Command arguments. */
516 /** Private data for pattern items. */
517 struct parse_item_priv {
518 enum rte_flow_item_type type; /**< Item type. */
519 uint32_t size; /**< Size of item specification structure. */
522 #define PRIV_ITEM(t, s) \
523 (&(const struct parse_item_priv){ \
524 .type = RTE_FLOW_ITEM_TYPE_ ## t, \
528 /** Private data for actions. */
529 struct parse_action_priv {
530 enum rte_flow_action_type type; /**< Action type. */
531 uint32_t size; /**< Size of action configuration structure. */
534 #define PRIV_ACTION(t, s) \
535 (&(const struct parse_action_priv){ \
536 .type = RTE_FLOW_ACTION_TYPE_ ## t, \
540 static const enum index next_vc_attr[] = {
550 static const enum index next_destroy_attr[] = {
556 static const enum index next_list_attr[] = {
562 static const enum index item_param[] = {
571 static const enum index item_param_is[] = {
576 static const enum index next_item[] = {
612 ITEM_ICMP6_ND_OPT_SLA_ETH,
613 ITEM_ICMP6_ND_OPT_TLA_ETH,
618 static const enum index item_fuzzy[] = {
624 static const enum index item_any[] = {
630 static const enum index item_vf[] = {
636 static const enum index item_phy_port[] = {
642 static const enum index item_port_id[] = {
648 static const enum index item_mark[] = {
654 static const enum index item_raw[] = {
664 static const enum index item_eth[] = {
672 static const enum index item_vlan[] = {
677 ITEM_VLAN_INNER_TYPE,
682 static const enum index item_ipv4[] = {
692 static const enum index item_ipv6[] = {
703 static const enum index item_icmp[] = {
710 static const enum index item_udp[] = {
717 static const enum index item_tcp[] = {
725 static const enum index item_sctp[] = {
734 static const enum index item_vxlan[] = {
740 static const enum index item_e_tag[] = {
741 ITEM_E_TAG_GRP_ECID_B,
746 static const enum index item_nvgre[] = {
752 static const enum index item_mpls[] = {
758 static const enum index item_gre[] = {
764 static const enum index item_gtp[] = {
770 static const enum index item_geneve[] = {
777 static const enum index item_vxlan_gpe[] = {
783 static const enum index item_arp_eth_ipv4[] = {
784 ITEM_ARP_ETH_IPV4_SHA,
785 ITEM_ARP_ETH_IPV4_SPA,
786 ITEM_ARP_ETH_IPV4_THA,
787 ITEM_ARP_ETH_IPV4_TPA,
792 static const enum index item_ipv6_ext[] = {
793 ITEM_IPV6_EXT_NEXT_HDR,
798 static const enum index item_icmp6[] = {
805 static const enum index item_icmp6_nd_ns[] = {
806 ITEM_ICMP6_ND_NS_TARGET_ADDR,
811 static const enum index item_icmp6_nd_na[] = {
812 ITEM_ICMP6_ND_NA_TARGET_ADDR,
817 static const enum index item_icmp6_nd_opt[] = {
818 ITEM_ICMP6_ND_OPT_TYPE,
823 static const enum index item_icmp6_nd_opt_sla_eth[] = {
824 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
829 static const enum index item_icmp6_nd_opt_tla_eth[] = {
830 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
835 static const enum index item_meta[] = {
841 static const enum index next_action[] = {
857 ACTION_OF_SET_MPLS_TTL,
858 ACTION_OF_DEC_MPLS_TTL,
859 ACTION_OF_SET_NW_TTL,
860 ACTION_OF_DEC_NW_TTL,
861 ACTION_OF_COPY_TTL_OUT,
862 ACTION_OF_COPY_TTL_IN,
865 ACTION_OF_SET_VLAN_VID,
866 ACTION_OF_SET_VLAN_PCP,
875 ACTION_MPLSOUDP_ENCAP,
876 ACTION_MPLSOUDP_DECAP,
891 static const enum index action_mark[] = {
897 static const enum index action_queue[] = {
903 static const enum index action_count[] = {
910 static const enum index action_rss[] = {
921 static const enum index action_vf[] = {
928 static const enum index action_phy_port[] = {
929 ACTION_PHY_PORT_ORIGINAL,
930 ACTION_PHY_PORT_INDEX,
935 static const enum index action_port_id[] = {
936 ACTION_PORT_ID_ORIGINAL,
942 static const enum index action_meter[] = {
948 static const enum index action_of_set_mpls_ttl[] = {
949 ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
954 static const enum index action_of_set_nw_ttl[] = {
955 ACTION_OF_SET_NW_TTL_NW_TTL,
960 static const enum index action_of_push_vlan[] = {
961 ACTION_OF_PUSH_VLAN_ETHERTYPE,
966 static const enum index action_of_set_vlan_vid[] = {
967 ACTION_OF_SET_VLAN_VID_VLAN_VID,
972 static const enum index action_of_set_vlan_pcp[] = {
973 ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
978 static const enum index action_of_pop_mpls[] = {
979 ACTION_OF_POP_MPLS_ETHERTYPE,
984 static const enum index action_of_push_mpls[] = {
985 ACTION_OF_PUSH_MPLS_ETHERTYPE,
990 static const enum index action_set_ipv4_src[] = {
991 ACTION_SET_IPV4_SRC_IPV4_SRC,
996 static const enum index action_set_mac_src[] = {
997 ACTION_SET_MAC_SRC_MAC_SRC,
1002 static const enum index action_set_ipv4_dst[] = {
1003 ACTION_SET_IPV4_DST_IPV4_DST,
1008 static const enum index action_set_ipv6_src[] = {
1009 ACTION_SET_IPV6_SRC_IPV6_SRC,
1014 static const enum index action_set_ipv6_dst[] = {
1015 ACTION_SET_IPV6_DST_IPV6_DST,
1020 static const enum index action_set_tp_src[] = {
1021 ACTION_SET_TP_SRC_TP_SRC,
1026 static const enum index action_set_tp_dst[] = {
1027 ACTION_SET_TP_DST_TP_DST,
1032 static const enum index action_set_ttl[] = {
1038 static const enum index action_jump[] = {
1044 static const enum index action_set_mac_dst[] = {
1045 ACTION_SET_MAC_DST_MAC_DST,
1050 static int parse_init(struct context *, const struct token *,
1051 const char *, unsigned int,
1052 void *, unsigned int);
1053 static int parse_vc(struct context *, const struct token *,
1054 const char *, unsigned int,
1055 void *, unsigned int);
1056 static int parse_vc_spec(struct context *, const struct token *,
1057 const char *, unsigned int, void *, unsigned int);
1058 static int parse_vc_conf(struct context *, const struct token *,
1059 const char *, unsigned int, void *, unsigned int);
1060 static int parse_vc_action_rss(struct context *, const struct token *,
1061 const char *, unsigned int, void *,
1063 static int parse_vc_action_rss_func(struct context *, const struct token *,
1064 const char *, unsigned int, void *,
1066 static int parse_vc_action_rss_type(struct context *, const struct token *,
1067 const char *, unsigned int, void *,
1069 static int parse_vc_action_rss_queue(struct context *, const struct token *,
1070 const char *, unsigned int, void *,
1072 static int parse_vc_action_vxlan_encap(struct context *, const struct token *,
1073 const char *, unsigned int, void *,
1075 static int parse_vc_action_nvgre_encap(struct context *, const struct token *,
1076 const char *, unsigned int, void *,
1078 static int parse_vc_action_l2_encap(struct context *, const struct token *,
1079 const char *, unsigned int, void *,
1081 static int parse_vc_action_l2_decap(struct context *, const struct token *,
1082 const char *, unsigned int, void *,
1084 static int parse_vc_action_mplsoudp_encap(struct context *,
1085 const struct token *, const char *,
1086 unsigned int, void *, unsigned int);
1087 static int parse_vc_action_mplsoudp_decap(struct context *,
1088 const struct token *, const char *,
1089 unsigned int, void *, unsigned int);
1090 static int parse_destroy(struct context *, const struct token *,
1091 const char *, unsigned int,
1092 void *, unsigned int);
1093 static int parse_flush(struct context *, const struct token *,
1094 const char *, unsigned int,
1095 void *, unsigned int);
1096 static int parse_query(struct context *, const struct token *,
1097 const char *, unsigned int,
1098 void *, unsigned int);
1099 static int parse_action(struct context *, const struct token *,
1100 const char *, unsigned int,
1101 void *, unsigned int);
1102 static int parse_list(struct context *, const struct token *,
1103 const char *, unsigned int,
1104 void *, unsigned int);
1105 static int parse_isolate(struct context *, const struct token *,
1106 const char *, unsigned int,
1107 void *, unsigned int);
1108 static int parse_int(struct context *, const struct token *,
1109 const char *, unsigned int,
1110 void *, unsigned int);
1111 static int parse_prefix(struct context *, const struct token *,
1112 const char *, unsigned int,
1113 void *, unsigned int);
1114 static int parse_boolean(struct context *, const struct token *,
1115 const char *, unsigned int,
1116 void *, unsigned int);
1117 static int parse_string(struct context *, const struct token *,
1118 const char *, unsigned int,
1119 void *, unsigned int);
1120 static int parse_mac_addr(struct context *, const struct token *,
1121 const char *, unsigned int,
1122 void *, unsigned int);
1123 static int parse_ipv4_addr(struct context *, const struct token *,
1124 const char *, unsigned int,
1125 void *, unsigned int);
1126 static int parse_ipv6_addr(struct context *, const struct token *,
1127 const char *, unsigned int,
1128 void *, unsigned int);
1129 static int parse_port(struct context *, const struct token *,
1130 const char *, unsigned int,
1131 void *, unsigned int);
1132 static int comp_none(struct context *, const struct token *,
1133 unsigned int, char *, unsigned int);
1134 static int comp_boolean(struct context *, const struct token *,
1135 unsigned int, char *, unsigned int);
1136 static int comp_action(struct context *, const struct token *,
1137 unsigned int, char *, unsigned int);
1138 static int comp_port(struct context *, const struct token *,
1139 unsigned int, char *, unsigned int);
1140 static int comp_rule_id(struct context *, const struct token *,
1141 unsigned int, char *, unsigned int);
1142 static int comp_vc_action_rss_type(struct context *, const struct token *,
1143 unsigned int, char *, unsigned int);
1144 static int comp_vc_action_rss_queue(struct context *, const struct token *,
1145 unsigned int, char *, unsigned int);
1147 /** Token definitions. */
1148 static const struct token token_list[] = {
1149 /* Special tokens. */
1152 .help = "null entry, abused as the entry point",
1153 .next = NEXT(NEXT_ENTRY(FLOW)),
1158 .help = "command may end here",
1160 /* Common tokens. */
1164 .help = "integer value",
1169 .name = "{unsigned}",
1171 .help = "unsigned integer value",
1178 .help = "prefix length for bit-mask",
1179 .call = parse_prefix,
1183 .name = "{boolean}",
1185 .help = "any boolean value",
1186 .call = parse_boolean,
1187 .comp = comp_boolean,
1192 .help = "fixed string",
1193 .call = parse_string,
1197 .name = "{MAC address}",
1199 .help = "standard MAC address notation",
1200 .call = parse_mac_addr,
1204 .name = "{IPv4 address}",
1205 .type = "IPV4 ADDRESS",
1206 .help = "standard IPv4 address notation",
1207 .call = parse_ipv4_addr,
1211 .name = "{IPv6 address}",
1212 .type = "IPV6 ADDRESS",
1213 .help = "standard IPv6 address notation",
1214 .call = parse_ipv6_addr,
1218 .name = "{rule id}",
1220 .help = "rule identifier",
1222 .comp = comp_rule_id,
1225 .name = "{port_id}",
1227 .help = "port identifier",
1232 .name = "{group_id}",
1234 .help = "group identifier",
1238 [PRIORITY_LEVEL] = {
1241 .help = "priority level",
1245 /* Top-level command. */
1248 .type = "{command} {port_id} [{arg} [...]]",
1249 .help = "manage ingress/egress flow rules",
1250 .next = NEXT(NEXT_ENTRY
1260 /* Sub-level commands. */
1263 .help = "check whether a flow rule can be created",
1264 .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
1265 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1270 .help = "create a flow rule",
1271 .next = NEXT(next_vc_attr, NEXT_ENTRY(PORT_ID)),
1272 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1277 .help = "destroy specific flow rules",
1278 .next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)),
1279 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1280 .call = parse_destroy,
1284 .help = "destroy all flow rules",
1285 .next = NEXT(NEXT_ENTRY(PORT_ID)),
1286 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1287 .call = parse_flush,
1291 .help = "query an existing flow rule",
1292 .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
1293 NEXT_ENTRY(RULE_ID),
1294 NEXT_ENTRY(PORT_ID)),
1295 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
1296 ARGS_ENTRY(struct buffer, args.query.rule),
1297 ARGS_ENTRY(struct buffer, port)),
1298 .call = parse_query,
1302 .help = "list existing flow rules",
1303 .next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)),
1304 .args = ARGS(ARGS_ENTRY(struct buffer, port)),
1309 .help = "restrict ingress traffic to the defined flow rules",
1310 .next = NEXT(NEXT_ENTRY(BOOLEAN),
1311 NEXT_ENTRY(PORT_ID)),
1312 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set),
1313 ARGS_ENTRY(struct buffer, port)),
1314 .call = parse_isolate,
1316 /* Destroy arguments. */
1319 .help = "specify a rule identifier",
1320 .next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)),
1321 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
1322 .call = parse_destroy,
1324 /* Query arguments. */
1328 .help = "action to query, must be part of the rule",
1329 .call = parse_action,
1330 .comp = comp_action,
1332 /* List arguments. */
1335 .help = "specify a group",
1336 .next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)),
1337 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)),
1340 /* Validate/create attributes. */
1343 .help = "specify a group",
1344 .next = NEXT(next_vc_attr, NEXT_ENTRY(GROUP_ID)),
1345 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)),
1350 .help = "specify a priority level",
1351 .next = NEXT(next_vc_attr, NEXT_ENTRY(PRIORITY_LEVEL)),
1352 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)),
1357 .help = "affect rule to ingress",
1358 .next = NEXT(next_vc_attr),
1363 .help = "affect rule to egress",
1364 .next = NEXT(next_vc_attr),
1369 .help = "apply rule directly to endpoints found in pattern",
1370 .next = NEXT(next_vc_attr),
1373 /* Validate/create pattern. */
1376 .help = "submit a list of pattern items",
1377 .next = NEXT(next_item),
1382 .help = "match value perfectly (with full bit-mask)",
1383 .call = parse_vc_spec,
1385 [ITEM_PARAM_SPEC] = {
1387 .help = "match value according to configured bit-mask",
1388 .call = parse_vc_spec,
1390 [ITEM_PARAM_LAST] = {
1392 .help = "specify upper bound to establish a range",
1393 .call = parse_vc_spec,
1395 [ITEM_PARAM_MASK] = {
1397 .help = "specify bit-mask with relevant bits set to one",
1398 .call = parse_vc_spec,
1400 [ITEM_PARAM_PREFIX] = {
1402 .help = "generate bit-mask from a prefix length",
1403 .call = parse_vc_spec,
1407 .help = "specify next pattern item",
1408 .next = NEXT(next_item),
1412 .help = "end list of pattern items",
1413 .priv = PRIV_ITEM(END, 0),
1414 .next = NEXT(NEXT_ENTRY(ACTIONS)),
1419 .help = "no-op pattern item",
1420 .priv = PRIV_ITEM(VOID, 0),
1421 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1426 .help = "perform actions when pattern does not match",
1427 .priv = PRIV_ITEM(INVERT, 0),
1428 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1433 .help = "match any protocol for the current layer",
1434 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)),
1435 .next = NEXT(item_any),
1440 .help = "number of layers covered",
1441 .next = NEXT(item_any, NEXT_ENTRY(UNSIGNED), item_param),
1442 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)),
1446 .help = "match traffic from/to the physical function",
1447 .priv = PRIV_ITEM(PF, 0),
1448 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)),
1453 .help = "match traffic from/to a virtual function ID",
1454 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)),
1455 .next = NEXT(item_vf),
1461 .next = NEXT(item_vf, NEXT_ENTRY(UNSIGNED), item_param),
1462 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)),
1466 .help = "match traffic from/to a specific physical port",
1467 .priv = PRIV_ITEM(PHY_PORT,
1468 sizeof(struct rte_flow_item_phy_port)),
1469 .next = NEXT(item_phy_port),
1472 [ITEM_PHY_PORT_INDEX] = {
1474 .help = "physical port index",
1475 .next = NEXT(item_phy_port, NEXT_ENTRY(UNSIGNED), item_param),
1476 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)),
1480 .help = "match traffic from/to a given DPDK port ID",
1481 .priv = PRIV_ITEM(PORT_ID,
1482 sizeof(struct rte_flow_item_port_id)),
1483 .next = NEXT(item_port_id),
1486 [ITEM_PORT_ID_ID] = {
1488 .help = "DPDK port ID",
1489 .next = NEXT(item_port_id, NEXT_ENTRY(UNSIGNED), item_param),
1490 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)),
1494 .help = "match traffic against value set in previously matched rule",
1495 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)),
1496 .next = NEXT(item_mark),
1501 .help = "Integer value to match against",
1502 .next = NEXT(item_mark, NEXT_ENTRY(UNSIGNED), item_param),
1503 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)),
1507 .help = "match an arbitrary byte string",
1508 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE),
1509 .next = NEXT(item_raw),
1512 [ITEM_RAW_RELATIVE] = {
1514 .help = "look for pattern after the previous item",
1515 .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
1516 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
1519 [ITEM_RAW_SEARCH] = {
1521 .help = "search pattern from offset (see also limit)",
1522 .next = NEXT(item_raw, NEXT_ENTRY(BOOLEAN), item_param),
1523 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw,
1526 [ITEM_RAW_OFFSET] = {
1528 .help = "absolute or relative offset for pattern",
1529 .next = NEXT(item_raw, NEXT_ENTRY(INTEGER), item_param),
1530 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)),
1532 [ITEM_RAW_LIMIT] = {
1534 .help = "search area limit for start of pattern",
1535 .next = NEXT(item_raw, NEXT_ENTRY(UNSIGNED), item_param),
1536 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)),
1538 [ITEM_RAW_PATTERN] = {
1540 .help = "byte string to look for",
1541 .next = NEXT(item_raw,
1543 NEXT_ENTRY(ITEM_PARAM_IS,
1546 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern),
1547 ARGS_ENTRY(struct rte_flow_item_raw, length),
1548 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw),
1549 ITEM_RAW_PATTERN_SIZE)),
1553 .help = "match Ethernet header",
1554 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)),
1555 .next = NEXT(item_eth),
1560 .help = "destination MAC",
1561 .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
1562 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)),
1566 .help = "source MAC",
1567 .next = NEXT(item_eth, NEXT_ENTRY(MAC_ADDR), item_param),
1568 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)),
1572 .help = "EtherType",
1573 .next = NEXT(item_eth, NEXT_ENTRY(UNSIGNED), item_param),
1574 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)),
1578 .help = "match 802.1Q/ad VLAN tag",
1579 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)),
1580 .next = NEXT(item_vlan),
1585 .help = "tag control information",
1586 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1587 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)),
1591 .help = "priority code point",
1592 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1593 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1598 .help = "drop eligible indicator",
1599 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1600 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1605 .help = "VLAN identifier",
1606 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1607 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan,
1610 [ITEM_VLAN_INNER_TYPE] = {
1611 .name = "inner_type",
1612 .help = "inner EtherType",
1613 .next = NEXT(item_vlan, NEXT_ENTRY(UNSIGNED), item_param),
1614 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan,
1619 .help = "match IPv4 header",
1620 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)),
1621 .next = NEXT(item_ipv4),
1626 .help = "type of service",
1627 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1628 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1629 hdr.type_of_service)),
1633 .help = "time to live",
1634 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1635 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1638 [ITEM_IPV4_PROTO] = {
1640 .help = "next protocol ID",
1641 .next = NEXT(item_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
1642 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1643 hdr.next_proto_id)),
1647 .help = "source address",
1648 .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
1649 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1654 .help = "destination address",
1655 .next = NEXT(item_ipv4, NEXT_ENTRY(IPV4_ADDR), item_param),
1656 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4,
1661 .help = "match IPv6 header",
1662 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)),
1663 .next = NEXT(item_ipv6),
1668 .help = "traffic class",
1669 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
1670 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
1672 "\x0f\xf0\x00\x00")),
1674 [ITEM_IPV6_FLOW] = {
1676 .help = "flow label",
1677 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
1678 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6,
1680 "\x00\x0f\xff\xff")),
1682 [ITEM_IPV6_PROTO] = {
1684 .help = "protocol (next header)",
1685 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
1686 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1691 .help = "hop limit",
1692 .next = NEXT(item_ipv6, NEXT_ENTRY(UNSIGNED), item_param),
1693 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1698 .help = "source address",
1699 .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
1700 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1705 .help = "destination address",
1706 .next = NEXT(item_ipv6, NEXT_ENTRY(IPV6_ADDR), item_param),
1707 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6,
1712 .help = "match ICMP header",
1713 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)),
1714 .next = NEXT(item_icmp),
1717 [ITEM_ICMP_TYPE] = {
1719 .help = "ICMP packet type",
1720 .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
1721 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
1724 [ITEM_ICMP_CODE] = {
1726 .help = "ICMP packet code",
1727 .next = NEXT(item_icmp, NEXT_ENTRY(UNSIGNED), item_param),
1728 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp,
1733 .help = "match UDP header",
1734 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)),
1735 .next = NEXT(item_udp),
1740 .help = "UDP source port",
1741 .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
1742 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
1747 .help = "UDP destination port",
1748 .next = NEXT(item_udp, NEXT_ENTRY(UNSIGNED), item_param),
1749 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp,
1754 .help = "match TCP header",
1755 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)),
1756 .next = NEXT(item_tcp),
1761 .help = "TCP source port",
1762 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
1763 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
1768 .help = "TCP destination port",
1769 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
1770 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
1773 [ITEM_TCP_FLAGS] = {
1775 .help = "TCP flags",
1776 .next = NEXT(item_tcp, NEXT_ENTRY(UNSIGNED), item_param),
1777 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp,
1782 .help = "match SCTP header",
1783 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)),
1784 .next = NEXT(item_sctp),
1789 .help = "SCTP source port",
1790 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1791 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1796 .help = "SCTP destination port",
1797 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1798 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1803 .help = "validation tag",
1804 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1805 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1808 [ITEM_SCTP_CKSUM] = {
1811 .next = NEXT(item_sctp, NEXT_ENTRY(UNSIGNED), item_param),
1812 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp,
1817 .help = "match VXLAN header",
1818 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)),
1819 .next = NEXT(item_vxlan),
1822 [ITEM_VXLAN_VNI] = {
1824 .help = "VXLAN identifier",
1825 .next = NEXT(item_vxlan, NEXT_ENTRY(UNSIGNED), item_param),
1826 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)),
1830 .help = "match E-Tag header",
1831 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
1832 .next = NEXT(item_e_tag),
1835 [ITEM_E_TAG_GRP_ECID_B] = {
1836 .name = "grp_ecid_b",
1837 .help = "GRP and E-CID base",
1838 .next = NEXT(item_e_tag, NEXT_ENTRY(UNSIGNED), item_param),
1839 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag,
1845 .help = "match NVGRE header",
1846 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
1847 .next = NEXT(item_nvgre),
1850 [ITEM_NVGRE_TNI] = {
1852 .help = "virtual subnet ID",
1853 .next = NEXT(item_nvgre, NEXT_ENTRY(UNSIGNED), item_param),
1854 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)),
1858 .help = "match MPLS header",
1859 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)),
1860 .next = NEXT(item_mpls),
1863 [ITEM_MPLS_LABEL] = {
1865 .help = "MPLS label",
1866 .next = NEXT(item_mpls, NEXT_ENTRY(UNSIGNED), item_param),
1867 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls,
1873 .help = "match GRE header",
1874 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)),
1875 .next = NEXT(item_gre),
1878 [ITEM_GRE_PROTO] = {
1880 .help = "GRE protocol type",
1881 .next = NEXT(item_gre, NEXT_ENTRY(UNSIGNED), item_param),
1882 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre,
1887 .help = "fuzzy pattern match, expect faster than default",
1888 .priv = PRIV_ITEM(FUZZY,
1889 sizeof(struct rte_flow_item_fuzzy)),
1890 .next = NEXT(item_fuzzy),
1893 [ITEM_FUZZY_THRESH] = {
1895 .help = "match accuracy threshold",
1896 .next = NEXT(item_fuzzy, NEXT_ENTRY(UNSIGNED), item_param),
1897 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy,
1902 .help = "match GTP header",
1903 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
1904 .next = NEXT(item_gtp),
1909 .help = "tunnel endpoint identifier",
1910 .next = NEXT(item_gtp, NEXT_ENTRY(UNSIGNED), item_param),
1911 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
1915 .help = "match GTP header",
1916 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
1917 .next = NEXT(item_gtp),
1922 .help = "match GTP header",
1923 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
1924 .next = NEXT(item_gtp),
1929 .help = "match GENEVE header",
1930 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
1931 .next = NEXT(item_geneve),
1934 [ITEM_GENEVE_VNI] = {
1936 .help = "virtual network identifier",
1937 .next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
1938 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)),
1940 [ITEM_GENEVE_PROTO] = {
1942 .help = "GENEVE protocol type",
1943 .next = NEXT(item_geneve, NEXT_ENTRY(UNSIGNED), item_param),
1944 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
1947 [ITEM_VXLAN_GPE] = {
1948 .name = "vxlan-gpe",
1949 .help = "match VXLAN-GPE header",
1950 .priv = PRIV_ITEM(VXLAN_GPE,
1951 sizeof(struct rte_flow_item_vxlan_gpe)),
1952 .next = NEXT(item_vxlan_gpe),
1955 [ITEM_VXLAN_GPE_VNI] = {
1957 .help = "VXLAN-GPE identifier",
1958 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(UNSIGNED), item_param),
1959 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe,
1962 [ITEM_ARP_ETH_IPV4] = {
1963 .name = "arp_eth_ipv4",
1964 .help = "match ARP header for Ethernet/IPv4",
1965 .priv = PRIV_ITEM(ARP_ETH_IPV4,
1966 sizeof(struct rte_flow_item_arp_eth_ipv4)),
1967 .next = NEXT(item_arp_eth_ipv4),
1970 [ITEM_ARP_ETH_IPV4_SHA] = {
1972 .help = "sender hardware address",
1973 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
1975 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
1978 [ITEM_ARP_ETH_IPV4_SPA] = {
1980 .help = "sender IPv4 address",
1981 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
1983 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
1986 [ITEM_ARP_ETH_IPV4_THA] = {
1988 .help = "target hardware address",
1989 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
1991 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
1994 [ITEM_ARP_ETH_IPV4_TPA] = {
1996 .help = "target IPv4 address",
1997 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
1999 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
2004 .help = "match presence of any IPv6 extension header",
2005 .priv = PRIV_ITEM(IPV6_EXT,
2006 sizeof(struct rte_flow_item_ipv6_ext)),
2007 .next = NEXT(item_ipv6_ext),
2010 [ITEM_IPV6_EXT_NEXT_HDR] = {
2012 .help = "next header",
2013 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(UNSIGNED), item_param),
2014 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
2019 .help = "match any ICMPv6 header",
2020 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
2021 .next = NEXT(item_icmp6),
2024 [ITEM_ICMP6_TYPE] = {
2026 .help = "ICMPv6 type",
2027 .next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
2028 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
2031 [ITEM_ICMP6_CODE] = {
2033 .help = "ICMPv6 code",
2034 .next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
2035 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
2038 [ITEM_ICMP6_ND_NS] = {
2039 .name = "icmp6_nd_ns",
2040 .help = "match ICMPv6 neighbor discovery solicitation",
2041 .priv = PRIV_ITEM(ICMP6_ND_NS,
2042 sizeof(struct rte_flow_item_icmp6_nd_ns)),
2043 .next = NEXT(item_icmp6_nd_ns),
2046 [ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
2047 .name = "target_addr",
2048 .help = "target address",
2049 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(IPV6_ADDR),
2051 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
2054 [ITEM_ICMP6_ND_NA] = {
2055 .name = "icmp6_nd_na",
2056 .help = "match ICMPv6 neighbor discovery advertisement",
2057 .priv = PRIV_ITEM(ICMP6_ND_NA,
2058 sizeof(struct rte_flow_item_icmp6_nd_na)),
2059 .next = NEXT(item_icmp6_nd_na),
2062 [ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
2063 .name = "target_addr",
2064 .help = "target address",
2065 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(IPV6_ADDR),
2067 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
2070 [ITEM_ICMP6_ND_OPT] = {
2071 .name = "icmp6_nd_opt",
2072 .help = "match presence of any ICMPv6 neighbor discovery"
2074 .priv = PRIV_ITEM(ICMP6_ND_OPT,
2075 sizeof(struct rte_flow_item_icmp6_nd_opt)),
2076 .next = NEXT(item_icmp6_nd_opt),
2079 [ITEM_ICMP6_ND_OPT_TYPE] = {
2081 .help = "ND option type",
2082 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(UNSIGNED),
2084 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
2087 [ITEM_ICMP6_ND_OPT_SLA_ETH] = {
2088 .name = "icmp6_nd_opt_sla_eth",
2089 .help = "match ICMPv6 neighbor discovery source Ethernet"
2090 " link-layer address option",
2092 (ICMP6_ND_OPT_SLA_ETH,
2093 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
2094 .next = NEXT(item_icmp6_nd_opt_sla_eth),
2097 [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
2099 .help = "source Ethernet LLA",
2100 .next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(MAC_ADDR),
2102 .args = ARGS(ARGS_ENTRY_HTON
2103 (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
2105 [ITEM_ICMP6_ND_OPT_TLA_ETH] = {
2106 .name = "icmp6_nd_opt_tla_eth",
2107 .help = "match ICMPv6 neighbor discovery target Ethernet"
2108 " link-layer address option",
2110 (ICMP6_ND_OPT_TLA_ETH,
2111 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
2112 .next = NEXT(item_icmp6_nd_opt_tla_eth),
2115 [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
2117 .help = "target Ethernet LLA",
2118 .next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(MAC_ADDR),
2120 .args = ARGS(ARGS_ENTRY_HTON
2121 (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
2125 .help = "match metadata header",
2126 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)),
2127 .next = NEXT(item_meta),
2130 [ITEM_META_DATA] = {
2132 .help = "metadata value",
2133 .next = NEXT(item_meta, NEXT_ENTRY(UNSIGNED), item_param_is),
2134 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_meta,
2135 data, "\xff\xff\xff\xff")),
2138 /* Validate/create actions. */
2141 .help = "submit a list of associated actions",
2142 .next = NEXT(next_action),
2147 .help = "specify next action",
2148 .next = NEXT(next_action),
2152 .help = "end list of actions",
2153 .priv = PRIV_ACTION(END, 0),
2158 .help = "no-op action",
2159 .priv = PRIV_ACTION(VOID, 0),
2160 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2163 [ACTION_PASSTHRU] = {
2165 .help = "let subsequent rule process matched packets",
2166 .priv = PRIV_ACTION(PASSTHRU, 0),
2167 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2172 .help = "redirect traffic to a given group",
2173 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)),
2174 .next = NEXT(action_jump),
2177 [ACTION_JUMP_GROUP] = {
2179 .help = "group to redirect traffic to",
2180 .next = NEXT(action_jump, NEXT_ENTRY(UNSIGNED)),
2181 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)),
2182 .call = parse_vc_conf,
2186 .help = "attach 32 bit value to packets",
2187 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)),
2188 .next = NEXT(action_mark),
2191 [ACTION_MARK_ID] = {
2193 .help = "32 bit value to return with packets",
2194 .next = NEXT(action_mark, NEXT_ENTRY(UNSIGNED)),
2195 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)),
2196 .call = parse_vc_conf,
2200 .help = "flag packets",
2201 .priv = PRIV_ACTION(FLAG, 0),
2202 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2207 .help = "assign packets to a given queue index",
2208 .priv = PRIV_ACTION(QUEUE,
2209 sizeof(struct rte_flow_action_queue)),
2210 .next = NEXT(action_queue),
2213 [ACTION_QUEUE_INDEX] = {
2215 .help = "queue index to use",
2216 .next = NEXT(action_queue, NEXT_ENTRY(UNSIGNED)),
2217 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
2218 .call = parse_vc_conf,
2222 .help = "drop packets (note: passthru has priority)",
2223 .priv = PRIV_ACTION(DROP, 0),
2224 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2229 .help = "enable counters for this rule",
2230 .priv = PRIV_ACTION(COUNT,
2231 sizeof(struct rte_flow_action_count)),
2232 .next = NEXT(action_count),
2235 [ACTION_COUNT_ID] = {
2236 .name = "identifier",
2237 .help = "counter identifier to use",
2238 .next = NEXT(action_count, NEXT_ENTRY(UNSIGNED)),
2239 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)),
2240 .call = parse_vc_conf,
2242 [ACTION_COUNT_SHARED] = {
2244 .help = "shared counter",
2245 .next = NEXT(action_count, NEXT_ENTRY(BOOLEAN)),
2246 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_count,
2248 .call = parse_vc_conf,
2252 .help = "spread packets among several queues",
2253 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)),
2254 .next = NEXT(action_rss),
2255 .call = parse_vc_action_rss,
2257 [ACTION_RSS_FUNC] = {
2259 .help = "RSS hash function to apply",
2260 .next = NEXT(action_rss,
2261 NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT,
2262 ACTION_RSS_FUNC_TOEPLITZ,
2263 ACTION_RSS_FUNC_SIMPLE_XOR)),
2265 [ACTION_RSS_FUNC_DEFAULT] = {
2267 .help = "default hash function",
2268 .call = parse_vc_action_rss_func,
2270 [ACTION_RSS_FUNC_TOEPLITZ] = {
2272 .help = "Toeplitz hash function",
2273 .call = parse_vc_action_rss_func,
2275 [ACTION_RSS_FUNC_SIMPLE_XOR] = {
2276 .name = "simple_xor",
2277 .help = "simple XOR hash function",
2278 .call = parse_vc_action_rss_func,
2280 [ACTION_RSS_LEVEL] = {
2282 .help = "encapsulation level for \"types\"",
2283 .next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
2284 .args = ARGS(ARGS_ENTRY_ARB
2285 (offsetof(struct action_rss_data, conf) +
2286 offsetof(struct rte_flow_action_rss, level),
2287 sizeof(((struct rte_flow_action_rss *)0)->
2290 [ACTION_RSS_TYPES] = {
2292 .help = "specific RSS hash types",
2293 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
2295 [ACTION_RSS_TYPE] = {
2297 .help = "RSS hash type",
2298 .call = parse_vc_action_rss_type,
2299 .comp = comp_vc_action_rss_type,
2301 [ACTION_RSS_KEY] = {
2303 .help = "RSS hash key",
2304 .next = NEXT(action_rss, NEXT_ENTRY(STRING)),
2305 .args = ARGS(ARGS_ENTRY_ARB(0, 0),
2307 (offsetof(struct action_rss_data, conf) +
2308 offsetof(struct rte_flow_action_rss, key_len),
2309 sizeof(((struct rte_flow_action_rss *)0)->
2311 ARGS_ENTRY(struct action_rss_data, key)),
2313 [ACTION_RSS_KEY_LEN] = {
2315 .help = "RSS hash key length in bytes",
2316 .next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
2317 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
2318 (offsetof(struct action_rss_data, conf) +
2319 offsetof(struct rte_flow_action_rss, key_len),
2320 sizeof(((struct rte_flow_action_rss *)0)->
2323 RSS_HASH_KEY_LENGTH)),
2325 [ACTION_RSS_QUEUES] = {
2327 .help = "queue indices to use",
2328 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)),
2329 .call = parse_vc_conf,
2331 [ACTION_RSS_QUEUE] = {
2333 .help = "queue index",
2334 .call = parse_vc_action_rss_queue,
2335 .comp = comp_vc_action_rss_queue,
2339 .help = "direct traffic to physical function",
2340 .priv = PRIV_ACTION(PF, 0),
2341 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2346 .help = "direct traffic to a virtual function ID",
2347 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)),
2348 .next = NEXT(action_vf),
2351 [ACTION_VF_ORIGINAL] = {
2353 .help = "use original VF ID if possible",
2354 .next = NEXT(action_vf, NEXT_ENTRY(BOOLEAN)),
2355 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf,
2357 .call = parse_vc_conf,
2362 .next = NEXT(action_vf, NEXT_ENTRY(UNSIGNED)),
2363 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)),
2364 .call = parse_vc_conf,
2366 [ACTION_PHY_PORT] = {
2368 .help = "direct packets to physical port index",
2369 .priv = PRIV_ACTION(PHY_PORT,
2370 sizeof(struct rte_flow_action_phy_port)),
2371 .next = NEXT(action_phy_port),
2374 [ACTION_PHY_PORT_ORIGINAL] = {
2376 .help = "use original port index if possible",
2377 .next = NEXT(action_phy_port, NEXT_ENTRY(BOOLEAN)),
2378 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port,
2380 .call = parse_vc_conf,
2382 [ACTION_PHY_PORT_INDEX] = {
2384 .help = "physical port index",
2385 .next = NEXT(action_phy_port, NEXT_ENTRY(UNSIGNED)),
2386 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port,
2388 .call = parse_vc_conf,
2390 [ACTION_PORT_ID] = {
2392 .help = "direct matching traffic to a given DPDK port ID",
2393 .priv = PRIV_ACTION(PORT_ID,
2394 sizeof(struct rte_flow_action_port_id)),
2395 .next = NEXT(action_port_id),
2398 [ACTION_PORT_ID_ORIGINAL] = {
2400 .help = "use original DPDK port ID if possible",
2401 .next = NEXT(action_port_id, NEXT_ENTRY(BOOLEAN)),
2402 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id,
2404 .call = parse_vc_conf,
2406 [ACTION_PORT_ID_ID] = {
2408 .help = "DPDK port ID",
2409 .next = NEXT(action_port_id, NEXT_ENTRY(UNSIGNED)),
2410 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)),
2411 .call = parse_vc_conf,
2415 .help = "meter the directed packets at given id",
2416 .priv = PRIV_ACTION(METER,
2417 sizeof(struct rte_flow_action_meter)),
2418 .next = NEXT(action_meter),
2421 [ACTION_METER_ID] = {
2423 .help = "meter id to use",
2424 .next = NEXT(action_meter, NEXT_ENTRY(UNSIGNED)),
2425 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
2426 .call = parse_vc_conf,
2428 [ACTION_OF_SET_MPLS_TTL] = {
2429 .name = "of_set_mpls_ttl",
2430 .help = "OpenFlow's OFPAT_SET_MPLS_TTL",
2433 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
2434 .next = NEXT(action_of_set_mpls_ttl),
2437 [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
2440 .next = NEXT(action_of_set_mpls_ttl, NEXT_ENTRY(UNSIGNED)),
2441 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
2443 .call = parse_vc_conf,
2445 [ACTION_OF_DEC_MPLS_TTL] = {
2446 .name = "of_dec_mpls_ttl",
2447 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
2448 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
2449 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2452 [ACTION_OF_SET_NW_TTL] = {
2453 .name = "of_set_nw_ttl",
2454 .help = "OpenFlow's OFPAT_SET_NW_TTL",
2457 sizeof(struct rte_flow_action_of_set_nw_ttl)),
2458 .next = NEXT(action_of_set_nw_ttl),
2461 [ACTION_OF_SET_NW_TTL_NW_TTL] = {
2464 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(UNSIGNED)),
2465 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
2467 .call = parse_vc_conf,
2469 [ACTION_OF_DEC_NW_TTL] = {
2470 .name = "of_dec_nw_ttl",
2471 .help = "OpenFlow's OFPAT_DEC_NW_TTL",
2472 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
2473 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2476 [ACTION_OF_COPY_TTL_OUT] = {
2477 .name = "of_copy_ttl_out",
2478 .help = "OpenFlow's OFPAT_COPY_TTL_OUT",
2479 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
2480 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2483 [ACTION_OF_COPY_TTL_IN] = {
2484 .name = "of_copy_ttl_in",
2485 .help = "OpenFlow's OFPAT_COPY_TTL_IN",
2486 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
2487 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2490 [ACTION_OF_POP_VLAN] = {
2491 .name = "of_pop_vlan",
2492 .help = "OpenFlow's OFPAT_POP_VLAN",
2493 .priv = PRIV_ACTION(OF_POP_VLAN, 0),
2494 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2497 [ACTION_OF_PUSH_VLAN] = {
2498 .name = "of_push_vlan",
2499 .help = "OpenFlow's OFPAT_PUSH_VLAN",
2502 sizeof(struct rte_flow_action_of_push_vlan)),
2503 .next = NEXT(action_of_push_vlan),
2506 [ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
2507 .name = "ethertype",
2508 .help = "EtherType",
2509 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(UNSIGNED)),
2510 .args = ARGS(ARGS_ENTRY_HTON
2511 (struct rte_flow_action_of_push_vlan,
2513 .call = parse_vc_conf,
2515 [ACTION_OF_SET_VLAN_VID] = {
2516 .name = "of_set_vlan_vid",
2517 .help = "OpenFlow's OFPAT_SET_VLAN_VID",
2520 sizeof(struct rte_flow_action_of_set_vlan_vid)),
2521 .next = NEXT(action_of_set_vlan_vid),
2524 [ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
2527 .next = NEXT(action_of_set_vlan_vid, NEXT_ENTRY(UNSIGNED)),
2528 .args = ARGS(ARGS_ENTRY_HTON
2529 (struct rte_flow_action_of_set_vlan_vid,
2531 .call = parse_vc_conf,
2533 [ACTION_OF_SET_VLAN_PCP] = {
2534 .name = "of_set_vlan_pcp",
2535 .help = "OpenFlow's OFPAT_SET_VLAN_PCP",
2538 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
2539 .next = NEXT(action_of_set_vlan_pcp),
2542 [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
2544 .help = "VLAN priority",
2545 .next = NEXT(action_of_set_vlan_pcp, NEXT_ENTRY(UNSIGNED)),
2546 .args = ARGS(ARGS_ENTRY_HTON
2547 (struct rte_flow_action_of_set_vlan_pcp,
2549 .call = parse_vc_conf,
2551 [ACTION_OF_POP_MPLS] = {
2552 .name = "of_pop_mpls",
2553 .help = "OpenFlow's OFPAT_POP_MPLS",
2554 .priv = PRIV_ACTION(OF_POP_MPLS,
2555 sizeof(struct rte_flow_action_of_pop_mpls)),
2556 .next = NEXT(action_of_pop_mpls),
2559 [ACTION_OF_POP_MPLS_ETHERTYPE] = {
2560 .name = "ethertype",
2561 .help = "EtherType",
2562 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(UNSIGNED)),
2563 .args = ARGS(ARGS_ENTRY_HTON
2564 (struct rte_flow_action_of_pop_mpls,
2566 .call = parse_vc_conf,
2568 [ACTION_OF_PUSH_MPLS] = {
2569 .name = "of_push_mpls",
2570 .help = "OpenFlow's OFPAT_PUSH_MPLS",
2573 sizeof(struct rte_flow_action_of_push_mpls)),
2574 .next = NEXT(action_of_push_mpls),
2577 [ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
2578 .name = "ethertype",
2579 .help = "EtherType",
2580 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(UNSIGNED)),
2581 .args = ARGS(ARGS_ENTRY_HTON
2582 (struct rte_flow_action_of_push_mpls,
2584 .call = parse_vc_conf,
2586 [ACTION_VXLAN_ENCAP] = {
2587 .name = "vxlan_encap",
2588 .help = "VXLAN encapsulation, uses configuration set by \"set"
2590 .priv = PRIV_ACTION(VXLAN_ENCAP,
2591 sizeof(struct action_vxlan_encap_data)),
2592 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2593 .call = parse_vc_action_vxlan_encap,
2595 [ACTION_VXLAN_DECAP] = {
2596 .name = "vxlan_decap",
2597 .help = "Performs a decapsulation action by stripping all"
2598 " headers of the VXLAN tunnel network overlay from the"
2600 .priv = PRIV_ACTION(VXLAN_DECAP, 0),
2601 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2604 [ACTION_NVGRE_ENCAP] = {
2605 .name = "nvgre_encap",
2606 .help = "NVGRE encapsulation, uses configuration set by \"set"
2608 .priv = PRIV_ACTION(NVGRE_ENCAP,
2609 sizeof(struct action_nvgre_encap_data)),
2610 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2611 .call = parse_vc_action_nvgre_encap,
2613 [ACTION_NVGRE_DECAP] = {
2614 .name = "nvgre_decap",
2615 .help = "Performs a decapsulation action by stripping all"
2616 " headers of the NVGRE tunnel network overlay from the"
2618 .priv = PRIV_ACTION(NVGRE_DECAP, 0),
2619 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2622 [ACTION_MPLSOUDP_ENCAP] = {
2623 .name = "mplsoudp_encap",
2624 .help = "mplsoudp encapsulation, uses configuration set by"
2625 " \"set mplsoudp_encap\"",
2626 .priv = PRIV_ACTION(RAW_ENCAP,
2627 sizeof(struct action_raw_encap_data)),
2628 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2629 .call = parse_vc_action_mplsoudp_encap,
2631 [ACTION_L2_ENCAP] = {
2633 .help = "l2 encapsulation, uses configuration set by"
2635 .priv = PRIV_ACTION(RAW_ENCAP,
2636 sizeof(struct action_raw_encap_data)),
2637 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2638 .call = parse_vc_action_l2_encap,
2640 [ACTION_L2_DECAP] = {
2642 .help = "l2 decap, uses configuration set by"
2643 " \"set l2_decap\"",
2644 .priv = PRIV_ACTION(RAW_DECAP,
2645 sizeof(struct action_raw_decap_data)),
2646 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2647 .call = parse_vc_action_l2_decap,
2649 [ACTION_MPLSOUDP_DECAP] = {
2650 .name = "mplsoudp_decap",
2651 .help = "mplsoudp decapsulation, uses configuration set by"
2652 " \"set mplsoudp_decap\"",
2653 .priv = PRIV_ACTION(RAW_DECAP,
2654 sizeof(struct action_raw_decap_data)),
2655 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2656 .call = parse_vc_action_mplsoudp_decap,
2658 [ACTION_SET_IPV4_SRC] = {
2659 .name = "set_ipv4_src",
2660 .help = "Set a new IPv4 source address in the outermost"
2662 .priv = PRIV_ACTION(SET_IPV4_SRC,
2663 sizeof(struct rte_flow_action_set_ipv4)),
2664 .next = NEXT(action_set_ipv4_src),
2667 [ACTION_SET_IPV4_SRC_IPV4_SRC] = {
2668 .name = "ipv4_addr",
2669 .help = "new IPv4 source address to set",
2670 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(IPV4_ADDR)),
2671 .args = ARGS(ARGS_ENTRY_HTON
2672 (struct rte_flow_action_set_ipv4, ipv4_addr)),
2673 .call = parse_vc_conf,
2675 [ACTION_SET_IPV4_DST] = {
2676 .name = "set_ipv4_dst",
2677 .help = "Set a new IPv4 destination address in the outermost"
2679 .priv = PRIV_ACTION(SET_IPV4_DST,
2680 sizeof(struct rte_flow_action_set_ipv4)),
2681 .next = NEXT(action_set_ipv4_dst),
2684 [ACTION_SET_IPV4_DST_IPV4_DST] = {
2685 .name = "ipv4_addr",
2686 .help = "new IPv4 destination address to set",
2687 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(IPV4_ADDR)),
2688 .args = ARGS(ARGS_ENTRY_HTON
2689 (struct rte_flow_action_set_ipv4, ipv4_addr)),
2690 .call = parse_vc_conf,
2692 [ACTION_SET_IPV6_SRC] = {
2693 .name = "set_ipv6_src",
2694 .help = "Set a new IPv6 source address in the outermost"
2696 .priv = PRIV_ACTION(SET_IPV6_SRC,
2697 sizeof(struct rte_flow_action_set_ipv6)),
2698 .next = NEXT(action_set_ipv6_src),
2701 [ACTION_SET_IPV6_SRC_IPV6_SRC] = {
2702 .name = "ipv6_addr",
2703 .help = "new IPv6 source address to set",
2704 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(IPV6_ADDR)),
2705 .args = ARGS(ARGS_ENTRY_HTON
2706 (struct rte_flow_action_set_ipv6, ipv6_addr)),
2707 .call = parse_vc_conf,
2709 [ACTION_SET_IPV6_DST] = {
2710 .name = "set_ipv6_dst",
2711 .help = "Set a new IPv6 destination address in the outermost"
2713 .priv = PRIV_ACTION(SET_IPV6_DST,
2714 sizeof(struct rte_flow_action_set_ipv6)),
2715 .next = NEXT(action_set_ipv6_dst),
2718 [ACTION_SET_IPV6_DST_IPV6_DST] = {
2719 .name = "ipv6_addr",
2720 .help = "new IPv6 destination address to set",
2721 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(IPV6_ADDR)),
2722 .args = ARGS(ARGS_ENTRY_HTON
2723 (struct rte_flow_action_set_ipv6, ipv6_addr)),
2724 .call = parse_vc_conf,
2726 [ACTION_SET_TP_SRC] = {
2727 .name = "set_tp_src",
2728 .help = "set a new source port number in the outermost"
2730 .priv = PRIV_ACTION(SET_TP_SRC,
2731 sizeof(struct rte_flow_action_set_tp)),
2732 .next = NEXT(action_set_tp_src),
2735 [ACTION_SET_TP_SRC_TP_SRC] = {
2737 .help = "new source port number to set",
2738 .next = NEXT(action_set_tp_src, NEXT_ENTRY(UNSIGNED)),
2739 .args = ARGS(ARGS_ENTRY_HTON
2740 (struct rte_flow_action_set_tp, port)),
2741 .call = parse_vc_conf,
2743 [ACTION_SET_TP_DST] = {
2744 .name = "set_tp_dst",
2745 .help = "set a new destination port number in the outermost"
2747 .priv = PRIV_ACTION(SET_TP_DST,
2748 sizeof(struct rte_flow_action_set_tp)),
2749 .next = NEXT(action_set_tp_dst),
2752 [ACTION_SET_TP_DST_TP_DST] = {
2754 .help = "new destination port number to set",
2755 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(UNSIGNED)),
2756 .args = ARGS(ARGS_ENTRY_HTON
2757 (struct rte_flow_action_set_tp, port)),
2758 .call = parse_vc_conf,
2760 [ACTION_MAC_SWAP] = {
2762 .help = "Swap the source and destination MAC addresses"
2763 " in the outermost Ethernet header",
2764 .priv = PRIV_ACTION(MAC_SWAP, 0),
2765 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2768 [ACTION_DEC_TTL] = {
2770 .help = "decrease network TTL if available",
2771 .priv = PRIV_ACTION(DEC_TTL, 0),
2772 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
2775 [ACTION_SET_TTL] = {
2777 .help = "set ttl value",
2778 .priv = PRIV_ACTION(SET_TTL,
2779 sizeof(struct rte_flow_action_set_ttl)),
2780 .next = NEXT(action_set_ttl),
2783 [ACTION_SET_TTL_TTL] = {
2784 .name = "ttl_value",
2785 .help = "new ttl value to set",
2786 .next = NEXT(action_set_ttl, NEXT_ENTRY(UNSIGNED)),
2787 .args = ARGS(ARGS_ENTRY_HTON
2788 (struct rte_flow_action_set_ttl, ttl_value)),
2789 .call = parse_vc_conf,
2791 [ACTION_SET_MAC_SRC] = {
2792 .name = "set_mac_src",
2793 .help = "set source mac address",
2794 .priv = PRIV_ACTION(SET_MAC_SRC,
2795 sizeof(struct rte_flow_action_set_mac)),
2796 .next = NEXT(action_set_mac_src),
2799 [ACTION_SET_MAC_SRC_MAC_SRC] = {
2801 .help = "new source mac address",
2802 .next = NEXT(action_set_mac_src, NEXT_ENTRY(MAC_ADDR)),
2803 .args = ARGS(ARGS_ENTRY_HTON
2804 (struct rte_flow_action_set_mac, mac_addr)),
2805 .call = parse_vc_conf,
2807 [ACTION_SET_MAC_DST] = {
2808 .name = "set_mac_dst",
2809 .help = "set destination mac address",
2810 .priv = PRIV_ACTION(SET_MAC_DST,
2811 sizeof(struct rte_flow_action_set_mac)),
2812 .next = NEXT(action_set_mac_dst),
2815 [ACTION_SET_MAC_DST_MAC_DST] = {
2817 .help = "new destination mac address to set",
2818 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(MAC_ADDR)),
2819 .args = ARGS(ARGS_ENTRY_HTON
2820 (struct rte_flow_action_set_mac, mac_addr)),
2821 .call = parse_vc_conf,
2825 /** Remove and return last entry from argument stack. */
2826 static const struct arg *
2827 pop_args(struct context *ctx)
2829 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL;
2832 /** Add entry on top of the argument stack. */
2834 push_args(struct context *ctx, const struct arg *arg)
2836 if (ctx->args_num == CTX_STACK_SIZE)
2838 ctx->args[ctx->args_num++] = arg;
2842 /** Spread value into buffer according to bit-mask. */
2844 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg)
2846 uint32_t i = arg->size;
2854 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
2863 unsigned int shift = 0;
2864 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub);
2866 for (shift = 0; arg->mask[i] >> shift; ++shift) {
2867 if (!(arg->mask[i] & (1 << shift)))
2872 *buf &= ~(1 << shift);
2873 *buf |= (val & 1) << shift;
2881 /** Compare a string with a partial one of a given length. */
2883 strcmp_partial(const char *full, const char *partial, size_t partial_len)
2885 int r = strncmp(full, partial, partial_len);
2889 if (strlen(full) <= partial_len)
2891 return full[partial_len];
2895 * Parse a prefix length and generate a bit-mask.
2897 * Last argument (ctx->args) is retrieved to determine mask size, storage
2898 * location and whether the result must use network byte ordering.
2901 parse_prefix(struct context *ctx, const struct token *token,
2902 const char *str, unsigned int len,
2903 void *buf, unsigned int size)
2905 const struct arg *arg = pop_args(ctx);
2906 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff";
2913 /* Argument is expected. */
2917 u = strtoumax(str, &end, 0);
2918 if (errno || (size_t)(end - str) != len)
2923 extra = arg_entry_bf_fill(NULL, 0, arg);
2932 if (!arg_entry_bf_fill(ctx->object, v, arg) ||
2933 !arg_entry_bf_fill(ctx->objmask, -1, arg))
2940 if (bytes > size || bytes + !!extra > size)
2944 buf = (uint8_t *)ctx->object + arg->offset;
2945 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
2947 memset((uint8_t *)buf + size - bytes, 0xff, bytes);
2948 memset(buf, 0x00, size - bytes);
2950 ((uint8_t *)buf)[size - bytes - 1] = conv[extra];
2954 memset(buf, 0xff, bytes);
2955 memset((uint8_t *)buf + bytes, 0x00, size - bytes);
2957 ((uint8_t *)buf)[bytes] = conv[extra];
2960 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
2963 push_args(ctx, arg);
2967 /** Default parsing function for token name matching. */
2969 parse_default(struct context *ctx, const struct token *token,
2970 const char *str, unsigned int len,
2971 void *buf, unsigned int size)
2976 if (strcmp_partial(token->name, str, len))
2981 /** Parse flow command, initialize output buffer for subsequent tokens. */
2983 parse_init(struct context *ctx, const struct token *token,
2984 const char *str, unsigned int len,
2985 void *buf, unsigned int size)
2987 struct buffer *out = buf;
2989 /* Token name must match. */
2990 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
2992 /* Nothing else to do if there is no buffer. */
2995 /* Make sure buffer is large enough. */
2996 if (size < sizeof(*out))
2998 /* Initialize buffer. */
2999 memset(out, 0x00, sizeof(*out));
3000 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out));
3003 ctx->objmask = NULL;
3007 /** Parse tokens for validate/create commands. */
3009 parse_vc(struct context *ctx, const struct token *token,
3010 const char *str, unsigned int len,
3011 void *buf, unsigned int size)
3013 struct buffer *out = buf;
3017 /* Token name must match. */
3018 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3020 /* Nothing else to do if there is no buffer. */
3023 if (!out->command) {
3024 if (ctx->curr != VALIDATE && ctx->curr != CREATE)
3026 if (sizeof(*out) > size)
3028 out->command = ctx->curr;
3031 ctx->objmask = NULL;
3032 out->args.vc.data = (uint8_t *)out + size;
3036 ctx->object = &out->args.vc.attr;
3037 ctx->objmask = NULL;
3038 switch (ctx->curr) {
3043 out->args.vc.attr.ingress = 1;
3046 out->args.vc.attr.egress = 1;
3049 out->args.vc.attr.transfer = 1;
3052 out->args.vc.pattern =
3053 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
3055 ctx->object = out->args.vc.pattern;
3056 ctx->objmask = NULL;
3059 out->args.vc.actions =
3060 (void *)RTE_ALIGN_CEIL((uintptr_t)
3061 (out->args.vc.pattern +
3062 out->args.vc.pattern_n),
3064 ctx->object = out->args.vc.actions;
3065 ctx->objmask = NULL;
3072 if (!out->args.vc.actions) {
3073 const struct parse_item_priv *priv = token->priv;
3074 struct rte_flow_item *item =
3075 out->args.vc.pattern + out->args.vc.pattern_n;
3077 data_size = priv->size * 3; /* spec, last, mask */
3078 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
3079 (out->args.vc.data - data_size),
3081 if ((uint8_t *)item + sizeof(*item) > data)
3083 *item = (struct rte_flow_item){
3086 ++out->args.vc.pattern_n;
3088 ctx->objmask = NULL;
3090 const struct parse_action_priv *priv = token->priv;
3091 struct rte_flow_action *action =
3092 out->args.vc.actions + out->args.vc.actions_n;
3094 data_size = priv->size; /* configuration */
3095 data = (void *)RTE_ALIGN_FLOOR((uintptr_t)
3096 (out->args.vc.data - data_size),
3098 if ((uint8_t *)action + sizeof(*action) > data)
3100 *action = (struct rte_flow_action){
3102 .conf = data_size ? data : NULL,
3104 ++out->args.vc.actions_n;
3105 ctx->object = action;
3106 ctx->objmask = NULL;
3108 memset(data, 0, data_size);
3109 out->args.vc.data = data;
3110 ctx->objdata = data_size;
3114 /** Parse pattern item parameter type. */
3116 parse_vc_spec(struct context *ctx, const struct token *token,
3117 const char *str, unsigned int len,
3118 void *buf, unsigned int size)
3120 struct buffer *out = buf;
3121 struct rte_flow_item *item;
3127 /* Token name must match. */
3128 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3130 /* Parse parameter types. */
3131 switch (ctx->curr) {
3132 static const enum index prefix[] = NEXT_ENTRY(PREFIX);
3138 case ITEM_PARAM_SPEC:
3141 case ITEM_PARAM_LAST:
3144 case ITEM_PARAM_PREFIX:
3145 /* Modify next token to expect a prefix. */
3146 if (ctx->next_num < 2)
3148 ctx->next[ctx->next_num - 2] = prefix;
3150 case ITEM_PARAM_MASK:
3156 /* Nothing else to do if there is no buffer. */
3159 if (!out->args.vc.pattern_n)
3161 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1];
3162 data_size = ctx->objdata / 3; /* spec, last, mask */
3163 /* Point to selected object. */
3164 ctx->object = out->args.vc.data + (data_size * index);
3166 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */
3167 item->mask = ctx->objmask;
3169 ctx->objmask = NULL;
3170 /* Update relevant item pointer. */
3171 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] =
3176 /** Parse action configuration field. */
3178 parse_vc_conf(struct context *ctx, const struct token *token,
3179 const char *str, unsigned int len,
3180 void *buf, unsigned int size)
3182 struct buffer *out = buf;
3185 /* Token name must match. */
3186 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3188 /* Nothing else to do if there is no buffer. */
3191 /* Point to selected object. */
3192 ctx->object = out->args.vc.data;
3193 ctx->objmask = NULL;
3197 /** Parse RSS action. */
3199 parse_vc_action_rss(struct context *ctx, const struct token *token,
3200 const char *str, unsigned int len,
3201 void *buf, unsigned int size)
3203 struct buffer *out = buf;
3204 struct rte_flow_action *action;
3205 struct action_rss_data *action_rss_data;
3209 ret = parse_vc(ctx, token, str, len, buf, size);
3212 /* Nothing else to do if there is no buffer. */
3215 if (!out->args.vc.actions_n)
3217 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3218 /* Point to selected object. */
3219 ctx->object = out->args.vc.data;
3220 ctx->objmask = NULL;
3221 /* Set up default configuration. */
3222 action_rss_data = ctx->object;
3223 *action_rss_data = (struct action_rss_data){
3224 .conf = (struct rte_flow_action_rss){
3225 .func = RTE_ETH_HASH_FUNCTION_DEFAULT,
3228 .key_len = sizeof(action_rss_data->key),
3229 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM),
3230 .key = action_rss_data->key,
3231 .queue = action_rss_data->queue,
3233 .key = "testpmd's default RSS hash key, "
3234 "override it for better balancing",
3237 for (i = 0; i < action_rss_data->conf.queue_num; ++i)
3238 action_rss_data->queue[i] = i;
3239 if (!port_id_is_invalid(ctx->port, DISABLED_WARN) &&
3240 ctx->port != (portid_t)RTE_PORT_ALL) {
3241 struct rte_eth_dev_info info;
3243 rte_eth_dev_info_get(ctx->port, &info);
3244 action_rss_data->conf.key_len =
3245 RTE_MIN(sizeof(action_rss_data->key),
3246 info.hash_key_size);
3248 action->conf = &action_rss_data->conf;
3253 * Parse func field for RSS action.
3255 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the
3256 * ACTION_RSS_FUNC_* index that called this function.
3259 parse_vc_action_rss_func(struct context *ctx, const struct token *token,
3260 const char *str, unsigned int len,
3261 void *buf, unsigned int size)
3263 struct action_rss_data *action_rss_data;
3264 enum rte_eth_hash_function func;
3268 /* Token name must match. */
3269 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3271 switch (ctx->curr) {
3272 case ACTION_RSS_FUNC_DEFAULT:
3273 func = RTE_ETH_HASH_FUNCTION_DEFAULT;
3275 case ACTION_RSS_FUNC_TOEPLITZ:
3276 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ;
3278 case ACTION_RSS_FUNC_SIMPLE_XOR:
3279 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR;
3286 action_rss_data = ctx->object;
3287 action_rss_data->conf.func = func;
3292 * Parse type field for RSS action.
3294 * Valid tokens are type field names and the "end" token.
3297 parse_vc_action_rss_type(struct context *ctx, const struct token *token,
3298 const char *str, unsigned int len,
3299 void *buf, unsigned int size)
3301 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
3302 struct action_rss_data *action_rss_data;
3308 if (ctx->curr != ACTION_RSS_TYPE)
3310 if (!(ctx->objdata >> 16) && ctx->object) {
3311 action_rss_data = ctx->object;
3312 action_rss_data->conf.types = 0;
3314 if (!strcmp_partial("end", str, len)) {
3315 ctx->objdata &= 0xffff;
3318 for (i = 0; rss_type_table[i].str; ++i)
3319 if (!strcmp_partial(rss_type_table[i].str, str, len))
3321 if (!rss_type_table[i].str)
3323 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
3325 if (ctx->next_num == RTE_DIM(ctx->next))
3327 ctx->next[ctx->next_num++] = next;
3330 action_rss_data = ctx->object;
3331 action_rss_data->conf.types |= rss_type_table[i].rss_type;
3336 * Parse queue field for RSS action.
3338 * Valid tokens are queue indices and the "end" token.
3341 parse_vc_action_rss_queue(struct context *ctx, const struct token *token,
3342 const char *str, unsigned int len,
3343 void *buf, unsigned int size)
3345 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
3346 struct action_rss_data *action_rss_data;
3353 if (ctx->curr != ACTION_RSS_QUEUE)
3355 i = ctx->objdata >> 16;
3356 if (!strcmp_partial("end", str, len)) {
3357 ctx->objdata &= 0xffff;
3360 if (i >= ACTION_RSS_QUEUE_NUM)
3363 ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) +
3364 i * sizeof(action_rss_data->queue[i]),
3365 sizeof(action_rss_data->queue[i]))))
3367 ret = parse_int(ctx, token, str, len, NULL, 0);
3373 ctx->objdata = i << 16 | (ctx->objdata & 0xffff);
3375 if (ctx->next_num == RTE_DIM(ctx->next))
3377 ctx->next[ctx->next_num++] = next;
3381 action_rss_data = ctx->object;
3382 action_rss_data->conf.queue_num = i;
3383 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL;
3387 /** Parse VXLAN encap action. */
3389 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token,
3390 const char *str, unsigned int len,
3391 void *buf, unsigned int size)
3393 struct buffer *out = buf;
3394 struct rte_flow_action *action;
3395 struct action_vxlan_encap_data *action_vxlan_encap_data;
3398 ret = parse_vc(ctx, token, str, len, buf, size);
3401 /* Nothing else to do if there is no buffer. */
3404 if (!out->args.vc.actions_n)
3406 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3407 /* Point to selected object. */
3408 ctx->object = out->args.vc.data;
3409 ctx->objmask = NULL;
3410 /* Set up default configuration. */
3411 action_vxlan_encap_data = ctx->object;
3412 *action_vxlan_encap_data = (struct action_vxlan_encap_data){
3413 .conf = (struct rte_flow_action_vxlan_encap){
3414 .definition = action_vxlan_encap_data->items,
3418 .type = RTE_FLOW_ITEM_TYPE_ETH,
3419 .spec = &action_vxlan_encap_data->item_eth,
3420 .mask = &rte_flow_item_eth_mask,
3423 .type = RTE_FLOW_ITEM_TYPE_VLAN,
3424 .spec = &action_vxlan_encap_data->item_vlan,
3425 .mask = &rte_flow_item_vlan_mask,
3428 .type = RTE_FLOW_ITEM_TYPE_IPV4,
3429 .spec = &action_vxlan_encap_data->item_ipv4,
3430 .mask = &rte_flow_item_ipv4_mask,
3433 .type = RTE_FLOW_ITEM_TYPE_UDP,
3434 .spec = &action_vxlan_encap_data->item_udp,
3435 .mask = &rte_flow_item_udp_mask,
3438 .type = RTE_FLOW_ITEM_TYPE_VXLAN,
3439 .spec = &action_vxlan_encap_data->item_vxlan,
3440 .mask = &rte_flow_item_vxlan_mask,
3443 .type = RTE_FLOW_ITEM_TYPE_END,
3448 .tci = vxlan_encap_conf.vlan_tci,
3452 .src_addr = vxlan_encap_conf.ipv4_src,
3453 .dst_addr = vxlan_encap_conf.ipv4_dst,
3456 .src_port = vxlan_encap_conf.udp_src,
3457 .dst_port = vxlan_encap_conf.udp_dst,
3459 .item_vxlan.flags = 0,
3461 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes,
3462 vxlan_encap_conf.eth_dst, ETHER_ADDR_LEN);
3463 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes,
3464 vxlan_encap_conf.eth_src, ETHER_ADDR_LEN);
3465 if (!vxlan_encap_conf.select_ipv4) {
3466 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr,
3467 &vxlan_encap_conf.ipv6_src,
3468 sizeof(vxlan_encap_conf.ipv6_src));
3469 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr,
3470 &vxlan_encap_conf.ipv6_dst,
3471 sizeof(vxlan_encap_conf.ipv6_dst));
3472 action_vxlan_encap_data->items[2] = (struct rte_flow_item){
3473 .type = RTE_FLOW_ITEM_TYPE_IPV6,
3474 .spec = &action_vxlan_encap_data->item_ipv6,
3475 .mask = &rte_flow_item_ipv6_mask,
3478 if (!vxlan_encap_conf.select_vlan)
3479 action_vxlan_encap_data->items[1].type =
3480 RTE_FLOW_ITEM_TYPE_VOID;
3481 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni,
3482 RTE_DIM(vxlan_encap_conf.vni));
3483 action->conf = &action_vxlan_encap_data->conf;
3487 /** Parse NVGRE encap action. */
3489 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token,
3490 const char *str, unsigned int len,
3491 void *buf, unsigned int size)
3493 struct buffer *out = buf;
3494 struct rte_flow_action *action;
3495 struct action_nvgre_encap_data *action_nvgre_encap_data;
3498 ret = parse_vc(ctx, token, str, len, buf, size);
3501 /* Nothing else to do if there is no buffer. */
3504 if (!out->args.vc.actions_n)
3506 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3507 /* Point to selected object. */
3508 ctx->object = out->args.vc.data;
3509 ctx->objmask = NULL;
3510 /* Set up default configuration. */
3511 action_nvgre_encap_data = ctx->object;
3512 *action_nvgre_encap_data = (struct action_nvgre_encap_data){
3513 .conf = (struct rte_flow_action_nvgre_encap){
3514 .definition = action_nvgre_encap_data->items,
3518 .type = RTE_FLOW_ITEM_TYPE_ETH,
3519 .spec = &action_nvgre_encap_data->item_eth,
3520 .mask = &rte_flow_item_eth_mask,
3523 .type = RTE_FLOW_ITEM_TYPE_VLAN,
3524 .spec = &action_nvgre_encap_data->item_vlan,
3525 .mask = &rte_flow_item_vlan_mask,
3528 .type = RTE_FLOW_ITEM_TYPE_IPV4,
3529 .spec = &action_nvgre_encap_data->item_ipv4,
3530 .mask = &rte_flow_item_ipv4_mask,
3533 .type = RTE_FLOW_ITEM_TYPE_NVGRE,
3534 .spec = &action_nvgre_encap_data->item_nvgre,
3535 .mask = &rte_flow_item_nvgre_mask,
3538 .type = RTE_FLOW_ITEM_TYPE_END,
3543 .tci = nvgre_encap_conf.vlan_tci,
3547 .src_addr = nvgre_encap_conf.ipv4_src,
3548 .dst_addr = nvgre_encap_conf.ipv4_dst,
3550 .item_nvgre.flow_id = 0,
3552 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes,
3553 nvgre_encap_conf.eth_dst, ETHER_ADDR_LEN);
3554 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes,
3555 nvgre_encap_conf.eth_src, ETHER_ADDR_LEN);
3556 if (!nvgre_encap_conf.select_ipv4) {
3557 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr,
3558 &nvgre_encap_conf.ipv6_src,
3559 sizeof(nvgre_encap_conf.ipv6_src));
3560 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr,
3561 &nvgre_encap_conf.ipv6_dst,
3562 sizeof(nvgre_encap_conf.ipv6_dst));
3563 action_nvgre_encap_data->items[2] = (struct rte_flow_item){
3564 .type = RTE_FLOW_ITEM_TYPE_IPV6,
3565 .spec = &action_nvgre_encap_data->item_ipv6,
3566 .mask = &rte_flow_item_ipv6_mask,
3569 if (!nvgre_encap_conf.select_vlan)
3570 action_nvgre_encap_data->items[1].type =
3571 RTE_FLOW_ITEM_TYPE_VOID;
3572 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni,
3573 RTE_DIM(nvgre_encap_conf.tni));
3574 action->conf = &action_nvgre_encap_data->conf;
3578 /** Parse l2 encap action. */
3580 parse_vc_action_l2_encap(struct context *ctx, const struct token *token,
3581 const char *str, unsigned int len,
3582 void *buf, unsigned int size)
3584 struct buffer *out = buf;
3585 struct rte_flow_action *action;
3586 struct action_raw_encap_data *action_encap_data;
3587 struct rte_flow_item_eth eth = { .type = 0, };
3588 struct rte_flow_item_vlan vlan = {
3589 .tci = mplsoudp_encap_conf.vlan_tci,
3595 ret = parse_vc(ctx, token, str, len, buf, size);
3598 /* Nothing else to do if there is no buffer. */
3601 if (!out->args.vc.actions_n)
3603 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3604 /* Point to selected object. */
3605 ctx->object = out->args.vc.data;
3606 ctx->objmask = NULL;
3607 /* Copy the headers to the buffer. */
3608 action_encap_data = ctx->object;
3609 *action_encap_data = (struct action_raw_encap_data) {
3610 .conf = (struct rte_flow_action_raw_encap){
3611 .data = action_encap_data->data,
3615 header = action_encap_data->data;
3616 if (l2_encap_conf.select_vlan)
3617 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3618 else if (l2_encap_conf.select_ipv4)
3619 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3621 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3622 memcpy(eth.dst.addr_bytes,
3623 l2_encap_conf.eth_dst, ETHER_ADDR_LEN);
3624 memcpy(eth.src.addr_bytes,
3625 l2_encap_conf.eth_src, ETHER_ADDR_LEN);
3626 memcpy(header, ð, sizeof(eth));
3627 header += sizeof(eth);
3628 if (l2_encap_conf.select_vlan) {
3629 if (l2_encap_conf.select_ipv4)
3630 vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3632 vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3633 memcpy(header, &vlan, sizeof(vlan));
3634 header += sizeof(vlan);
3636 action_encap_data->conf.size = header -
3637 action_encap_data->data;
3638 action->conf = &action_encap_data->conf;
3642 /** Parse l2 decap action. */
3644 parse_vc_action_l2_decap(struct context *ctx, const struct token *token,
3645 const char *str, unsigned int len,
3646 void *buf, unsigned int size)
3648 struct buffer *out = buf;
3649 struct rte_flow_action *action;
3650 struct action_raw_decap_data *action_decap_data;
3651 struct rte_flow_item_eth eth = { .type = 0, };
3652 struct rte_flow_item_vlan vlan = {
3653 .tci = mplsoudp_encap_conf.vlan_tci,
3659 ret = parse_vc(ctx, token, str, len, buf, size);
3662 /* Nothing else to do if there is no buffer. */
3665 if (!out->args.vc.actions_n)
3667 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3668 /* Point to selected object. */
3669 ctx->object = out->args.vc.data;
3670 ctx->objmask = NULL;
3671 /* Copy the headers to the buffer. */
3672 action_decap_data = ctx->object;
3673 *action_decap_data = (struct action_raw_decap_data) {
3674 .conf = (struct rte_flow_action_raw_decap){
3675 .data = action_decap_data->data,
3679 header = action_decap_data->data;
3680 if (l2_decap_conf.select_vlan)
3681 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3682 memcpy(header, ð, sizeof(eth));
3683 header += sizeof(eth);
3684 if (l2_decap_conf.select_vlan) {
3685 memcpy(header, &vlan, sizeof(vlan));
3686 header += sizeof(vlan);
3688 action_decap_data->conf.size = header -
3689 action_decap_data->data;
3690 action->conf = &action_decap_data->conf;
3694 /** Parse MPLSOUDP encap action. */
3696 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token,
3697 const char *str, unsigned int len,
3698 void *buf, unsigned int size)
3700 struct buffer *out = buf;
3701 struct rte_flow_action *action;
3702 struct action_raw_encap_data *action_encap_data;
3703 struct rte_flow_item_eth eth = { .type = 0, };
3704 struct rte_flow_item_vlan vlan = {
3705 .tci = mplsoudp_encap_conf.vlan_tci,
3708 struct rte_flow_item_ipv4 ipv4 = {
3710 .src_addr = mplsoudp_encap_conf.ipv4_src,
3711 .dst_addr = mplsoudp_encap_conf.ipv4_dst,
3712 .next_proto_id = IPPROTO_UDP,
3715 struct rte_flow_item_ipv6 ipv6 = {
3717 .proto = IPPROTO_UDP,
3720 struct rte_flow_item_udp udp = {
3722 .src_port = mplsoudp_encap_conf.udp_src,
3723 .dst_port = mplsoudp_encap_conf.udp_dst,
3726 struct rte_flow_item_mpls mpls;
3730 ret = parse_vc(ctx, token, str, len, buf, size);
3733 /* Nothing else to do if there is no buffer. */
3736 if (!out->args.vc.actions_n)
3738 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3739 /* Point to selected object. */
3740 ctx->object = out->args.vc.data;
3741 ctx->objmask = NULL;
3742 /* Copy the headers to the buffer. */
3743 action_encap_data = ctx->object;
3744 *action_encap_data = (struct action_raw_encap_data) {
3745 .conf = (struct rte_flow_action_raw_encap){
3746 .data = action_encap_data->data,
3751 header = action_encap_data->data;
3752 if (mplsoudp_encap_conf.select_vlan)
3753 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3754 else if (mplsoudp_encap_conf.select_ipv4)
3755 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3757 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3758 memcpy(eth.dst.addr_bytes,
3759 mplsoudp_encap_conf.eth_dst, ETHER_ADDR_LEN);
3760 memcpy(eth.src.addr_bytes,
3761 mplsoudp_encap_conf.eth_src, ETHER_ADDR_LEN);
3762 memcpy(header, ð, sizeof(eth));
3763 header += sizeof(eth);
3764 if (mplsoudp_encap_conf.select_vlan) {
3765 if (mplsoudp_encap_conf.select_ipv4)
3766 vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3768 vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3769 memcpy(header, &vlan, sizeof(vlan));
3770 header += sizeof(vlan);
3772 if (mplsoudp_encap_conf.select_ipv4) {
3773 memcpy(header, &ipv4, sizeof(ipv4));
3774 header += sizeof(ipv4);
3776 memcpy(&ipv6.hdr.src_addr,
3777 &mplsoudp_encap_conf.ipv6_src,
3778 sizeof(mplsoudp_encap_conf.ipv6_src));
3779 memcpy(&ipv6.hdr.dst_addr,
3780 &mplsoudp_encap_conf.ipv6_dst,
3781 sizeof(mplsoudp_encap_conf.ipv6_dst));
3782 memcpy(header, &ipv6, sizeof(ipv6));
3783 header += sizeof(ipv6);
3785 memcpy(header, &udp, sizeof(udp));
3786 header += sizeof(udp);
3787 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label,
3788 RTE_DIM(mplsoudp_encap_conf.label));
3789 memcpy(header, &mpls, sizeof(mpls));
3790 header += sizeof(mpls);
3791 action_encap_data->conf.size = header -
3792 action_encap_data->data;
3793 action->conf = &action_encap_data->conf;
3797 /** Parse MPLSOUDP decap action. */
3799 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token,
3800 const char *str, unsigned int len,
3801 void *buf, unsigned int size)
3803 struct buffer *out = buf;
3804 struct rte_flow_action *action;
3805 struct action_raw_decap_data *action_decap_data;
3806 struct rte_flow_item_eth eth = { .type = 0, };
3807 struct rte_flow_item_vlan vlan = {.tci = 0};
3808 struct rte_flow_item_ipv4 ipv4 = {
3810 .next_proto_id = IPPROTO_UDP,
3813 struct rte_flow_item_ipv6 ipv6 = {
3815 .proto = IPPROTO_UDP,
3818 struct rte_flow_item_udp udp = {
3820 .dst_port = rte_cpu_to_be_16(6635),
3823 struct rte_flow_item_mpls mpls;
3827 ret = parse_vc(ctx, token, str, len, buf, size);
3830 /* Nothing else to do if there is no buffer. */
3833 if (!out->args.vc.actions_n)
3835 action = &out->args.vc.actions[out->args.vc.actions_n - 1];
3836 /* Point to selected object. */
3837 ctx->object = out->args.vc.data;
3838 ctx->objmask = NULL;
3839 /* Copy the headers to the buffer. */
3840 action_decap_data = ctx->object;
3841 *action_decap_data = (struct action_raw_decap_data) {
3842 .conf = (struct rte_flow_action_raw_decap){
3843 .data = action_decap_data->data,
3847 header = action_decap_data->data;
3848 if (mplsoudp_decap_conf.select_vlan)
3849 eth.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
3850 else if (mplsoudp_encap_conf.select_ipv4)
3851 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3853 eth.type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3854 memcpy(eth.dst.addr_bytes,
3855 mplsoudp_encap_conf.eth_dst, ETHER_ADDR_LEN);
3856 memcpy(eth.src.addr_bytes,
3857 mplsoudp_encap_conf.eth_src, ETHER_ADDR_LEN);
3858 memcpy(header, ð, sizeof(eth));
3859 header += sizeof(eth);
3860 if (mplsoudp_encap_conf.select_vlan) {
3861 if (mplsoudp_encap_conf.select_ipv4)
3862 vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4);
3864 vlan.inner_type = rte_cpu_to_be_16(ETHER_TYPE_IPv6);
3865 memcpy(header, &vlan, sizeof(vlan));
3866 header += sizeof(vlan);
3868 if (mplsoudp_encap_conf.select_ipv4) {
3869 memcpy(header, &ipv4, sizeof(ipv4));
3870 header += sizeof(ipv4);
3872 memcpy(header, &ipv6, sizeof(ipv6));
3873 header += sizeof(ipv6);
3875 memcpy(header, &udp, sizeof(udp));
3876 header += sizeof(udp);
3877 memset(&mpls, 0, sizeof(mpls));
3878 memcpy(header, &mpls, sizeof(mpls));
3879 header += sizeof(mpls);
3880 action_decap_data->conf.size = header -
3881 action_decap_data->data;
3882 action->conf = &action_decap_data->conf;
3886 /** Parse tokens for destroy command. */
3888 parse_destroy(struct context *ctx, const struct token *token,
3889 const char *str, unsigned int len,
3890 void *buf, unsigned int size)
3892 struct buffer *out = buf;
3894 /* Token name must match. */
3895 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3897 /* Nothing else to do if there is no buffer. */
3900 if (!out->command) {
3901 if (ctx->curr != DESTROY)
3903 if (sizeof(*out) > size)
3905 out->command = ctx->curr;
3908 ctx->objmask = NULL;
3909 out->args.destroy.rule =
3910 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
3914 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
3915 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
3918 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
3919 ctx->objmask = NULL;
3923 /** Parse tokens for flush command. */
3925 parse_flush(struct context *ctx, const struct token *token,
3926 const char *str, unsigned int len,
3927 void *buf, unsigned int size)
3929 struct buffer *out = buf;
3931 /* Token name must match. */
3932 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3934 /* Nothing else to do if there is no buffer. */
3937 if (!out->command) {
3938 if (ctx->curr != FLUSH)
3940 if (sizeof(*out) > size)
3942 out->command = ctx->curr;
3945 ctx->objmask = NULL;
3950 /** Parse tokens for query command. */
3952 parse_query(struct context *ctx, const struct token *token,
3953 const char *str, unsigned int len,
3954 void *buf, unsigned int size)
3956 struct buffer *out = buf;
3958 /* Token name must match. */
3959 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
3961 /* Nothing else to do if there is no buffer. */
3964 if (!out->command) {
3965 if (ctx->curr != QUERY)
3967 if (sizeof(*out) > size)
3969 out->command = ctx->curr;
3972 ctx->objmask = NULL;
3977 /** Parse action names. */
3979 parse_action(struct context *ctx, const struct token *token,
3980 const char *str, unsigned int len,
3981 void *buf, unsigned int size)
3983 struct buffer *out = buf;
3984 const struct arg *arg = pop_args(ctx);
3988 /* Argument is expected. */
3991 /* Parse action name. */
3992 for (i = 0; next_action[i]; ++i) {
3993 const struct parse_action_priv *priv;
3995 token = &token_list[next_action[i]];
3996 if (strcmp_partial(token->name, str, len))
4002 memcpy((uint8_t *)ctx->object + arg->offset,
4008 push_args(ctx, arg);
4012 /** Parse tokens for list command. */
4014 parse_list(struct context *ctx, const struct token *token,
4015 const char *str, unsigned int len,
4016 void *buf, unsigned int size)
4018 struct buffer *out = buf;
4020 /* Token name must match. */
4021 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4023 /* Nothing else to do if there is no buffer. */
4026 if (!out->command) {
4027 if (ctx->curr != LIST)
4029 if (sizeof(*out) > size)
4031 out->command = ctx->curr;
4034 ctx->objmask = NULL;
4035 out->args.list.group =
4036 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
4040 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) +
4041 sizeof(*out->args.list.group)) > (uint8_t *)out + size)
4044 ctx->object = out->args.list.group + out->args.list.group_n++;
4045 ctx->objmask = NULL;
4049 /** Parse tokens for isolate command. */
4051 parse_isolate(struct context *ctx, const struct token *token,
4052 const char *str, unsigned int len,
4053 void *buf, unsigned int size)
4055 struct buffer *out = buf;
4057 /* Token name must match. */
4058 if (parse_default(ctx, token, str, len, NULL, 0) < 0)
4060 /* Nothing else to do if there is no buffer. */
4063 if (!out->command) {
4064 if (ctx->curr != ISOLATE)
4066 if (sizeof(*out) > size)
4068 out->command = ctx->curr;
4071 ctx->objmask = NULL;
4077 * Parse signed/unsigned integers 8 to 64-bit long.
4079 * Last argument (ctx->args) is retrieved to determine integer type and
4083 parse_int(struct context *ctx, const struct token *token,
4084 const char *str, unsigned int len,
4085 void *buf, unsigned int size)
4087 const struct arg *arg = pop_args(ctx);
4092 /* Argument is expected. */
4097 (uintmax_t)strtoimax(str, &end, 0) :
4098 strtoumax(str, &end, 0);
4099 if (errno || (size_t)(end - str) != len)
4102 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
4103 (intmax_t)u > (intmax_t)arg->max)) ||
4104 (!arg->sign && (u < arg->min || u > arg->max))))
4109 if (!arg_entry_bf_fill(ctx->object, u, arg) ||
4110 !arg_entry_bf_fill(ctx->objmask, -1, arg))
4114 buf = (uint8_t *)ctx->object + arg->offset;
4118 case sizeof(uint8_t):
4119 *(uint8_t *)buf = u;
4121 case sizeof(uint16_t):
4122 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u;
4124 case sizeof(uint8_t [3]):
4125 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
4127 ((uint8_t *)buf)[0] = u;
4128 ((uint8_t *)buf)[1] = u >> 8;
4129 ((uint8_t *)buf)[2] = u >> 16;
4133 ((uint8_t *)buf)[0] = u >> 16;
4134 ((uint8_t *)buf)[1] = u >> 8;
4135 ((uint8_t *)buf)[2] = u;
4137 case sizeof(uint32_t):
4138 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u;
4140 case sizeof(uint64_t):
4141 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u;
4146 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) {
4148 buf = (uint8_t *)ctx->objmask + arg->offset;
4153 push_args(ctx, arg);
4160 * Three arguments (ctx->args) are retrieved from the stack to store data,
4161 * its actual length and address (in that order).
4164 parse_string(struct context *ctx, const struct token *token,
4165 const char *str, unsigned int len,
4166 void *buf, unsigned int size)
4168 const struct arg *arg_data = pop_args(ctx);
4169 const struct arg *arg_len = pop_args(ctx);
4170 const struct arg *arg_addr = pop_args(ctx);
4171 char tmp[16]; /* Ought to be enough. */
4174 /* Arguments are expected. */
4178 push_args(ctx, arg_data);
4182 push_args(ctx, arg_len);
4183 push_args(ctx, arg_data);
4186 size = arg_data->size;
4187 /* Bit-mask fill is not supported. */
4188 if (arg_data->mask || size < len)
4192 /* Let parse_int() fill length information first. */
4193 ret = snprintf(tmp, sizeof(tmp), "%u", len);
4196 push_args(ctx, arg_len);
4197 ret = parse_int(ctx, token, tmp, ret, NULL, 0);
4202 buf = (uint8_t *)ctx->object + arg_data->offset;
4203 /* Output buffer is not necessarily NUL-terminated. */
4204 memcpy(buf, str, len);
4205 memset((uint8_t *)buf + len, 0x00, size - len);
4207 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
4208 /* Save address if requested. */
4209 if (arg_addr->size) {
4210 memcpy((uint8_t *)ctx->object + arg_addr->offset,
4212 (uint8_t *)ctx->object + arg_data->offset
4216 memcpy((uint8_t *)ctx->objmask + arg_addr->offset,
4218 (uint8_t *)ctx->objmask + arg_data->offset
4224 push_args(ctx, arg_addr);
4225 push_args(ctx, arg_len);
4226 push_args(ctx, arg_data);
4231 * Parse a MAC address.
4233 * Last argument (ctx->args) is retrieved to determine storage size and
4237 parse_mac_addr(struct context *ctx, const struct token *token,
4238 const char *str, unsigned int len,
4239 void *buf, unsigned int size)
4241 const struct arg *arg = pop_args(ctx);
4242 struct ether_addr tmp;
4246 /* Argument is expected. */
4250 /* Bit-mask fill is not supported. */
4251 if (arg->mask || size != sizeof(tmp))
4253 /* Only network endian is supported. */
4256 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size);
4257 if (ret < 0 || (unsigned int)ret != len)
4261 buf = (uint8_t *)ctx->object + arg->offset;
4262 memcpy(buf, &tmp, size);
4264 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
4267 push_args(ctx, arg);
4272 * Parse an IPv4 address.
4274 * Last argument (ctx->args) is retrieved to determine storage size and
4278 parse_ipv4_addr(struct context *ctx, const struct token *token,
4279 const char *str, unsigned int len,
4280 void *buf, unsigned int size)
4282 const struct arg *arg = pop_args(ctx);
4287 /* Argument is expected. */
4291 /* Bit-mask fill is not supported. */
4292 if (arg->mask || size != sizeof(tmp))
4294 /* Only network endian is supported. */
4297 memcpy(str2, str, len);
4299 ret = inet_pton(AF_INET, str2, &tmp);
4301 /* Attempt integer parsing. */
4302 push_args(ctx, arg);
4303 return parse_int(ctx, token, str, len, buf, size);
4307 buf = (uint8_t *)ctx->object + arg->offset;
4308 memcpy(buf, &tmp, size);
4310 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
4313 push_args(ctx, arg);
4318 * Parse an IPv6 address.
4320 * Last argument (ctx->args) is retrieved to determine storage size and
4324 parse_ipv6_addr(struct context *ctx, const struct token *token,
4325 const char *str, unsigned int len,
4326 void *buf, unsigned int size)
4328 const struct arg *arg = pop_args(ctx);
4330 struct in6_addr tmp;
4334 /* Argument is expected. */
4338 /* Bit-mask fill is not supported. */
4339 if (arg->mask || size != sizeof(tmp))
4341 /* Only network endian is supported. */
4344 memcpy(str2, str, len);
4346 ret = inet_pton(AF_INET6, str2, &tmp);
4351 buf = (uint8_t *)ctx->object + arg->offset;
4352 memcpy(buf, &tmp, size);
4354 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size);
4357 push_args(ctx, arg);
4361 /** Boolean values (even indices stand for false). */
4362 static const char *const boolean_name[] = {
4372 * Parse a boolean value.
4374 * Last argument (ctx->args) is retrieved to determine storage size and
4378 parse_boolean(struct context *ctx, const struct token *token,
4379 const char *str, unsigned int len,
4380 void *buf, unsigned int size)
4382 const struct arg *arg = pop_args(ctx);
4386 /* Argument is expected. */
4389 for (i = 0; boolean_name[i]; ++i)
4390 if (!strcmp_partial(boolean_name[i], str, len))
4392 /* Process token as integer. */
4393 if (boolean_name[i])
4394 str = i & 1 ? "1" : "0";
4395 push_args(ctx, arg);
4396 ret = parse_int(ctx, token, str, strlen(str), buf, size);
4397 return ret > 0 ? (int)len : ret;
4400 /** Parse port and update context. */
4402 parse_port(struct context *ctx, const struct token *token,
4403 const char *str, unsigned int len,
4404 void *buf, unsigned int size)
4406 struct buffer *out = &(struct buffer){ .port = 0 };
4414 ctx->objmask = NULL;
4415 size = sizeof(*out);
4417 ret = parse_int(ctx, token, str, len, out, size);
4419 ctx->port = out->port;
4425 /** No completion. */
4427 comp_none(struct context *ctx, const struct token *token,
4428 unsigned int ent, char *buf, unsigned int size)
4438 /** Complete boolean values. */
4440 comp_boolean(struct context *ctx, const struct token *token,
4441 unsigned int ent, char *buf, unsigned int size)
4447 for (i = 0; boolean_name[i]; ++i)
4448 if (buf && i == ent)
4449 return snprintf(buf, size, "%s", boolean_name[i]);
4455 /** Complete action names. */
4457 comp_action(struct context *ctx, const struct token *token,
4458 unsigned int ent, char *buf, unsigned int size)
4464 for (i = 0; next_action[i]; ++i)
4465 if (buf && i == ent)
4466 return snprintf(buf, size, "%s",
4467 token_list[next_action[i]].name);
4473 /** Complete available ports. */
4475 comp_port(struct context *ctx, const struct token *token,
4476 unsigned int ent, char *buf, unsigned int size)
4483 RTE_ETH_FOREACH_DEV(p) {
4484 if (buf && i == ent)
4485 return snprintf(buf, size, "%u", p);
4493 /** Complete available rule IDs. */
4495 comp_rule_id(struct context *ctx, const struct token *token,
4496 unsigned int ent, char *buf, unsigned int size)
4499 struct rte_port *port;
4500 struct port_flow *pf;
4503 if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
4504 ctx->port == (portid_t)RTE_PORT_ALL)
4506 port = &ports[ctx->port];
4507 for (pf = port->flow_list; pf != NULL; pf = pf->next) {
4508 if (buf && i == ent)
4509 return snprintf(buf, size, "%u", pf->id);
4517 /** Complete type field for RSS action. */
4519 comp_vc_action_rss_type(struct context *ctx, const struct token *token,
4520 unsigned int ent, char *buf, unsigned int size)
4526 for (i = 0; rss_type_table[i].str; ++i)
4531 return snprintf(buf, size, "%s", rss_type_table[ent].str);
4533 return snprintf(buf, size, "end");
4537 /** Complete queue field for RSS action. */
4539 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
4540 unsigned int ent, char *buf, unsigned int size)
4547 return snprintf(buf, size, "%u", ent);
4549 return snprintf(buf, size, "end");
4553 /** Internal context. */
4554 static struct context cmd_flow_context;
4556 /** Global parser instance (cmdline API). */
4557 cmdline_parse_inst_t cmd_flow;
4559 /** Initialize context. */
4561 cmd_flow_context_init(struct context *ctx)
4563 /* A full memset() is not necessary. */
4573 ctx->objmask = NULL;
4576 /** Parse a token (cmdline API). */
4578 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result,
4581 struct context *ctx = &cmd_flow_context;
4582 const struct token *token;
4583 const enum index *list;
4588 token = &token_list[ctx->curr];
4589 /* Check argument length. */
4592 for (len = 0; src[len]; ++len)
4593 if (src[len] == '#' || isspace(src[len]))
4597 /* Last argument and EOL detection. */
4598 for (i = len; src[i]; ++i)
4599 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n')
4601 else if (!isspace(src[i])) {
4606 if (src[i] == '\r' || src[i] == '\n') {
4610 /* Initialize context if necessary. */
4611 if (!ctx->next_num) {
4614 ctx->next[ctx->next_num++] = token->next[0];
4616 /* Process argument through candidates. */
4617 ctx->prev = ctx->curr;
4618 list = ctx->next[ctx->next_num - 1];
4619 for (i = 0; list[i]; ++i) {
4620 const struct token *next = &token_list[list[i]];
4623 ctx->curr = list[i];
4625 tmp = next->call(ctx, next, src, len, result, size);
4627 tmp = parse_default(ctx, next, src, len, result, size);
4628 if (tmp == -1 || tmp != len)
4636 /* Push subsequent tokens if any. */
4638 for (i = 0; token->next[i]; ++i) {
4639 if (ctx->next_num == RTE_DIM(ctx->next))
4641 ctx->next[ctx->next_num++] = token->next[i];
4643 /* Push arguments if any. */
4645 for (i = 0; token->args[i]; ++i) {
4646 if (ctx->args_num == RTE_DIM(ctx->args))
4648 ctx->args[ctx->args_num++] = token->args[i];
4653 /** Return number of completion entries (cmdline API). */
4655 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr)
4657 struct context *ctx = &cmd_flow_context;
4658 const struct token *token = &token_list[ctx->curr];
4659 const enum index *list;
4663 /* Count number of tokens in current list. */
4665 list = ctx->next[ctx->next_num - 1];
4667 list = token->next[0];
4668 for (i = 0; list[i]; ++i)
4673 * If there is a single token, use its completion callback, otherwise
4674 * return the number of entries.
4676 token = &token_list[list[0]];
4677 if (i == 1 && token->comp) {
4678 /* Save index for cmd_flow_get_help(). */
4679 ctx->prev = list[0];
4680 return token->comp(ctx, token, 0, NULL, 0);
4685 /** Return a completion entry (cmdline API). */
4687 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index,
4688 char *dst, unsigned int size)
4690 struct context *ctx = &cmd_flow_context;
4691 const struct token *token = &token_list[ctx->curr];
4692 const enum index *list;
4696 /* Count number of tokens in current list. */
4698 list = ctx->next[ctx->next_num - 1];
4700 list = token->next[0];
4701 for (i = 0; list[i]; ++i)
4705 /* If there is a single token, use its completion callback. */
4706 token = &token_list[list[0]];
4707 if (i == 1 && token->comp) {
4708 /* Save index for cmd_flow_get_help(). */
4709 ctx->prev = list[0];
4710 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0;
4712 /* Otherwise make sure the index is valid and use defaults. */
4715 token = &token_list[list[index]];
4716 snprintf(dst, size, "%s", token->name);
4717 /* Save index for cmd_flow_get_help(). */
4718 ctx->prev = list[index];
4722 /** Populate help strings for current token (cmdline API). */
4724 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size)
4726 struct context *ctx = &cmd_flow_context;
4727 const struct token *token = &token_list[ctx->prev];
4732 /* Set token type and update global help with details. */
4733 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN"));
4735 cmd_flow.help_str = token->help;
4737 cmd_flow.help_str = token->name;
4741 /** Token definition template (cmdline API). */
4742 static struct cmdline_token_hdr cmd_flow_token_hdr = {
4743 .ops = &(struct cmdline_token_ops){
4744 .parse = cmd_flow_parse,
4745 .complete_get_nb = cmd_flow_complete_get_nb,
4746 .complete_get_elt = cmd_flow_complete_get_elt,
4747 .get_help = cmd_flow_get_help,
4752 /** Populate the next dynamic token. */
4754 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr,
4755 cmdline_parse_token_hdr_t **hdr_inst)
4757 struct context *ctx = &cmd_flow_context;
4759 /* Always reinitialize context before requesting the first token. */
4760 if (!(hdr_inst - cmd_flow.tokens))
4761 cmd_flow_context_init(ctx);
4762 /* Return NULL when no more tokens are expected. */
4763 if (!ctx->next_num && ctx->curr) {
4767 /* Determine if command should end here. */
4768 if (ctx->eol && ctx->last && ctx->next_num) {
4769 const enum index *list = ctx->next[ctx->next_num - 1];
4772 for (i = 0; list[i]; ++i) {
4779 *hdr = &cmd_flow_token_hdr;
4782 /** Dispatch parsed buffer to function calls. */
4784 cmd_flow_parsed(const struct buffer *in)
4786 switch (in->command) {
4788 port_flow_validate(in->port, &in->args.vc.attr,
4789 in->args.vc.pattern, in->args.vc.actions);
4792 port_flow_create(in->port, &in->args.vc.attr,
4793 in->args.vc.pattern, in->args.vc.actions);
4796 port_flow_destroy(in->port, in->args.destroy.rule_n,
4797 in->args.destroy.rule);
4800 port_flow_flush(in->port);
4803 port_flow_query(in->port, in->args.query.rule,
4804 &in->args.query.action);
4807 port_flow_list(in->port, in->args.list.group_n,
4808 in->args.list.group);
4811 port_flow_isolate(in->port, in->args.isolate.set);
4818 /** Token generator and output processing callback (cmdline API). */
4820 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2)
4823 cmd_flow_tok(arg0, arg2);
4825 cmd_flow_parsed(arg0);
4828 /** Global parser instance (cmdline API). */
4829 cmdline_parse_inst_t cmd_flow = {
4831 .data = NULL, /**< Unused. */
4832 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */
4835 }, /**< Tokens are returned by cmd_flow_tok(). */