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