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