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 14 #include <rte_string_fns.h> 15 #include <rte_common.h> 16 #include <rte_ethdev.h> 17 #include <rte_byteorder.h> 18 #include <cmdline_parse.h> 19 #include <cmdline_parse_etheraddr.h> 20 #include <cmdline_parse_string.h> 21 #include <cmdline_parse_num.h> 22 #include <rte_flow.h> 23 #include <rte_hexdump.h> 24 #include <rte_vxlan.h> 25 #include <rte_gre.h> 26 #include <rte_mpls.h> 27 #include <rte_gtp.h> 28 #include <rte_geneve.h> 29 30 #include "testpmd.h" 31 32 /** Parser token indices. */ 33 enum index { 34 /* Special tokens. */ 35 ZERO = 0, 36 END, 37 START_SET, 38 END_SET, 39 40 /* Common tokens. */ 41 COMMON_INTEGER, 42 COMMON_UNSIGNED, 43 COMMON_PREFIX, 44 COMMON_BOOLEAN, 45 COMMON_STRING, 46 COMMON_HEX, 47 COMMON_FILE_PATH, 48 COMMON_MAC_ADDR, 49 COMMON_IPV4_ADDR, 50 COMMON_IPV6_ADDR, 51 COMMON_RULE_ID, 52 COMMON_PORT_ID, 53 COMMON_GROUP_ID, 54 COMMON_PRIORITY_LEVEL, 55 COMMON_INDIRECT_ACTION_ID, 56 COMMON_POLICY_ID, 57 COMMON_FLEX_HANDLE, 58 COMMON_FLEX_TOKEN, 59 COMMON_PATTERN_TEMPLATE_ID, 60 COMMON_ACTIONS_TEMPLATE_ID, 61 COMMON_TABLE_ID, 62 COMMON_QUEUE_ID, 63 64 /* TOP-level command. */ 65 ADD, 66 67 /* Top-level command. */ 68 SET, 69 /* Sub-leve commands. */ 70 SET_RAW_ENCAP, 71 SET_RAW_DECAP, 72 SET_RAW_INDEX, 73 SET_SAMPLE_ACTIONS, 74 SET_SAMPLE_INDEX, 75 76 /* Top-level command. */ 77 FLOW, 78 /* Sub-level commands. */ 79 INFO, 80 CONFIGURE, 81 PATTERN_TEMPLATE, 82 ACTIONS_TEMPLATE, 83 TABLE, 84 INDIRECT_ACTION, 85 VALIDATE, 86 CREATE, 87 DESTROY, 88 FLUSH, 89 DUMP, 90 QUERY, 91 LIST, 92 AGED, 93 ISOLATE, 94 TUNNEL, 95 FLEX, 96 QUEUE, 97 PUSH, 98 PULL, 99 100 /* Flex arguments */ 101 FLEX_ITEM_INIT, 102 FLEX_ITEM_CREATE, 103 FLEX_ITEM_DESTROY, 104 105 /* Pattern template arguments. */ 106 PATTERN_TEMPLATE_CREATE, 107 PATTERN_TEMPLATE_DESTROY, 108 PATTERN_TEMPLATE_CREATE_ID, 109 PATTERN_TEMPLATE_DESTROY_ID, 110 PATTERN_TEMPLATE_RELAXED_MATCHING, 111 PATTERN_TEMPLATE_INGRESS, 112 PATTERN_TEMPLATE_EGRESS, 113 PATTERN_TEMPLATE_TRANSFER, 114 PATTERN_TEMPLATE_SPEC, 115 116 /* Actions template arguments. */ 117 ACTIONS_TEMPLATE_CREATE, 118 ACTIONS_TEMPLATE_DESTROY, 119 ACTIONS_TEMPLATE_CREATE_ID, 120 ACTIONS_TEMPLATE_DESTROY_ID, 121 ACTIONS_TEMPLATE_INGRESS, 122 ACTIONS_TEMPLATE_EGRESS, 123 ACTIONS_TEMPLATE_TRANSFER, 124 ACTIONS_TEMPLATE_SPEC, 125 ACTIONS_TEMPLATE_MASK, 126 127 /* Queue arguments. */ 128 QUEUE_CREATE, 129 QUEUE_DESTROY, 130 131 /* Queue create arguments. */ 132 QUEUE_CREATE_ID, 133 QUEUE_CREATE_POSTPONE, 134 QUEUE_TEMPLATE_TABLE, 135 QUEUE_PATTERN_TEMPLATE, 136 QUEUE_ACTIONS_TEMPLATE, 137 QUEUE_SPEC, 138 139 /* Queue destroy arguments. */ 140 QUEUE_DESTROY_ID, 141 QUEUE_DESTROY_POSTPONE, 142 143 /* Push arguments. */ 144 PUSH_QUEUE, 145 146 /* Pull arguments. */ 147 PULL_QUEUE, 148 149 /* Table arguments. */ 150 TABLE_CREATE, 151 TABLE_DESTROY, 152 TABLE_CREATE_ID, 153 TABLE_DESTROY_ID, 154 TABLE_GROUP, 155 TABLE_PRIORITY, 156 TABLE_INGRESS, 157 TABLE_EGRESS, 158 TABLE_TRANSFER, 159 TABLE_RULES_NUMBER, 160 TABLE_PATTERN_TEMPLATE, 161 TABLE_ACTIONS_TEMPLATE, 162 163 /* Tunnel arguments. */ 164 TUNNEL_CREATE, 165 TUNNEL_CREATE_TYPE, 166 TUNNEL_LIST, 167 TUNNEL_DESTROY, 168 TUNNEL_DESTROY_ID, 169 170 /* Destroy arguments. */ 171 DESTROY_RULE, 172 173 /* Query arguments. */ 174 QUERY_ACTION, 175 176 /* List arguments. */ 177 LIST_GROUP, 178 179 /* Destroy aged flow arguments. */ 180 AGED_DESTROY, 181 182 /* Validate/create arguments. */ 183 VC_GROUP, 184 VC_PRIORITY, 185 VC_INGRESS, 186 VC_EGRESS, 187 VC_TRANSFER, 188 VC_TUNNEL_SET, 189 VC_TUNNEL_MATCH, 190 191 /* Dump arguments */ 192 DUMP_ALL, 193 DUMP_ONE, 194 195 /* Configure arguments */ 196 CONFIG_QUEUES_NUMBER, 197 CONFIG_QUEUES_SIZE, 198 CONFIG_COUNTERS_NUMBER, 199 CONFIG_AGING_OBJECTS_NUMBER, 200 CONFIG_METERS_NUMBER, 201 202 /* Indirect action arguments */ 203 INDIRECT_ACTION_CREATE, 204 INDIRECT_ACTION_UPDATE, 205 INDIRECT_ACTION_DESTROY, 206 INDIRECT_ACTION_QUERY, 207 208 /* Indirect action create arguments */ 209 INDIRECT_ACTION_CREATE_ID, 210 INDIRECT_ACTION_INGRESS, 211 INDIRECT_ACTION_EGRESS, 212 INDIRECT_ACTION_TRANSFER, 213 INDIRECT_ACTION_SPEC, 214 215 /* Indirect action destroy arguments */ 216 INDIRECT_ACTION_DESTROY_ID, 217 218 /* Validate/create pattern. */ 219 ITEM_PATTERN, 220 ITEM_PARAM_IS, 221 ITEM_PARAM_SPEC, 222 ITEM_PARAM_LAST, 223 ITEM_PARAM_MASK, 224 ITEM_PARAM_PREFIX, 225 ITEM_NEXT, 226 ITEM_END, 227 ITEM_VOID, 228 ITEM_INVERT, 229 ITEM_ANY, 230 ITEM_ANY_NUM, 231 ITEM_PF, 232 ITEM_VF, 233 ITEM_VF_ID, 234 ITEM_PHY_PORT, 235 ITEM_PHY_PORT_INDEX, 236 ITEM_PORT_ID, 237 ITEM_PORT_ID_ID, 238 ITEM_MARK, 239 ITEM_MARK_ID, 240 ITEM_RAW, 241 ITEM_RAW_RELATIVE, 242 ITEM_RAW_SEARCH, 243 ITEM_RAW_OFFSET, 244 ITEM_RAW_LIMIT, 245 ITEM_RAW_PATTERN, 246 ITEM_RAW_PATTERN_HEX, 247 ITEM_ETH, 248 ITEM_ETH_DST, 249 ITEM_ETH_SRC, 250 ITEM_ETH_TYPE, 251 ITEM_ETH_HAS_VLAN, 252 ITEM_VLAN, 253 ITEM_VLAN_TCI, 254 ITEM_VLAN_PCP, 255 ITEM_VLAN_DEI, 256 ITEM_VLAN_VID, 257 ITEM_VLAN_INNER_TYPE, 258 ITEM_VLAN_HAS_MORE_VLAN, 259 ITEM_IPV4, 260 ITEM_IPV4_VER_IHL, 261 ITEM_IPV4_TOS, 262 ITEM_IPV4_ID, 263 ITEM_IPV4_FRAGMENT_OFFSET, 264 ITEM_IPV4_TTL, 265 ITEM_IPV4_PROTO, 266 ITEM_IPV4_SRC, 267 ITEM_IPV4_DST, 268 ITEM_IPV6, 269 ITEM_IPV6_TC, 270 ITEM_IPV6_FLOW, 271 ITEM_IPV6_PROTO, 272 ITEM_IPV6_HOP, 273 ITEM_IPV6_SRC, 274 ITEM_IPV6_DST, 275 ITEM_IPV6_HAS_FRAG_EXT, 276 ITEM_ICMP, 277 ITEM_ICMP_TYPE, 278 ITEM_ICMP_CODE, 279 ITEM_ICMP_IDENT, 280 ITEM_ICMP_SEQ, 281 ITEM_UDP, 282 ITEM_UDP_SRC, 283 ITEM_UDP_DST, 284 ITEM_TCP, 285 ITEM_TCP_SRC, 286 ITEM_TCP_DST, 287 ITEM_TCP_FLAGS, 288 ITEM_SCTP, 289 ITEM_SCTP_SRC, 290 ITEM_SCTP_DST, 291 ITEM_SCTP_TAG, 292 ITEM_SCTP_CKSUM, 293 ITEM_VXLAN, 294 ITEM_VXLAN_VNI, 295 ITEM_VXLAN_LAST_RSVD, 296 ITEM_E_TAG, 297 ITEM_E_TAG_GRP_ECID_B, 298 ITEM_NVGRE, 299 ITEM_NVGRE_TNI, 300 ITEM_MPLS, 301 ITEM_MPLS_LABEL, 302 ITEM_MPLS_TC, 303 ITEM_MPLS_S, 304 ITEM_GRE, 305 ITEM_GRE_PROTO, 306 ITEM_GRE_C_RSVD0_VER, 307 ITEM_GRE_C_BIT, 308 ITEM_GRE_K_BIT, 309 ITEM_GRE_S_BIT, 310 ITEM_FUZZY, 311 ITEM_FUZZY_THRESH, 312 ITEM_GTP, 313 ITEM_GTP_FLAGS, 314 ITEM_GTP_MSG_TYPE, 315 ITEM_GTP_TEID, 316 ITEM_GTPC, 317 ITEM_GTPU, 318 ITEM_GENEVE, 319 ITEM_GENEVE_VNI, 320 ITEM_GENEVE_PROTO, 321 ITEM_GENEVE_OPTLEN, 322 ITEM_VXLAN_GPE, 323 ITEM_VXLAN_GPE_VNI, 324 ITEM_ARP_ETH_IPV4, 325 ITEM_ARP_ETH_IPV4_SHA, 326 ITEM_ARP_ETH_IPV4_SPA, 327 ITEM_ARP_ETH_IPV4_THA, 328 ITEM_ARP_ETH_IPV4_TPA, 329 ITEM_IPV6_EXT, 330 ITEM_IPV6_EXT_NEXT_HDR, 331 ITEM_IPV6_FRAG_EXT, 332 ITEM_IPV6_FRAG_EXT_NEXT_HDR, 333 ITEM_IPV6_FRAG_EXT_FRAG_DATA, 334 ITEM_IPV6_FRAG_EXT_ID, 335 ITEM_ICMP6, 336 ITEM_ICMP6_TYPE, 337 ITEM_ICMP6_CODE, 338 ITEM_ICMP6_ND_NS, 339 ITEM_ICMP6_ND_NS_TARGET_ADDR, 340 ITEM_ICMP6_ND_NA, 341 ITEM_ICMP6_ND_NA_TARGET_ADDR, 342 ITEM_ICMP6_ND_OPT, 343 ITEM_ICMP6_ND_OPT_TYPE, 344 ITEM_ICMP6_ND_OPT_SLA_ETH, 345 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA, 346 ITEM_ICMP6_ND_OPT_TLA_ETH, 347 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA, 348 ITEM_META, 349 ITEM_META_DATA, 350 ITEM_GRE_KEY, 351 ITEM_GRE_KEY_VALUE, 352 ITEM_GRE_OPTION, 353 ITEM_GRE_OPTION_CHECKSUM, 354 ITEM_GRE_OPTION_KEY, 355 ITEM_GRE_OPTION_SEQUENCE, 356 ITEM_GTP_PSC, 357 ITEM_GTP_PSC_QFI, 358 ITEM_GTP_PSC_PDU_T, 359 ITEM_PPPOES, 360 ITEM_PPPOED, 361 ITEM_PPPOE_SEID, 362 ITEM_PPPOE_PROTO_ID, 363 ITEM_HIGIG2, 364 ITEM_HIGIG2_CLASSIFICATION, 365 ITEM_HIGIG2_VID, 366 ITEM_TAG, 367 ITEM_TAG_DATA, 368 ITEM_TAG_INDEX, 369 ITEM_L2TPV3OIP, 370 ITEM_L2TPV3OIP_SESSION_ID, 371 ITEM_ESP, 372 ITEM_ESP_SPI, 373 ITEM_AH, 374 ITEM_AH_SPI, 375 ITEM_PFCP, 376 ITEM_PFCP_S_FIELD, 377 ITEM_PFCP_SEID, 378 ITEM_ECPRI, 379 ITEM_ECPRI_COMMON, 380 ITEM_ECPRI_COMMON_TYPE, 381 ITEM_ECPRI_COMMON_TYPE_IQ_DATA, 382 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL, 383 ITEM_ECPRI_COMMON_TYPE_DLY_MSR, 384 ITEM_ECPRI_MSG_IQ_DATA_PCID, 385 ITEM_ECPRI_MSG_RTC_CTRL_RTCID, 386 ITEM_ECPRI_MSG_DLY_MSR_MSRID, 387 ITEM_GENEVE_OPT, 388 ITEM_GENEVE_OPT_CLASS, 389 ITEM_GENEVE_OPT_TYPE, 390 ITEM_GENEVE_OPT_LENGTH, 391 ITEM_GENEVE_OPT_DATA, 392 ITEM_INTEGRITY, 393 ITEM_INTEGRITY_LEVEL, 394 ITEM_INTEGRITY_VALUE, 395 ITEM_CONNTRACK, 396 ITEM_POL_PORT, 397 ITEM_POL_METER, 398 ITEM_POL_POLICY, 399 ITEM_PORT_REPRESENTOR, 400 ITEM_PORT_REPRESENTOR_PORT_ID, 401 ITEM_REPRESENTED_PORT, 402 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID, 403 ITEM_FLEX, 404 ITEM_FLEX_ITEM_HANDLE, 405 ITEM_FLEX_PATTERN_HANDLE, 406 ITEM_L2TPV2, 407 ITEM_L2TPV2_TYPE, 408 ITEM_L2TPV2_TYPE_DATA, 409 ITEM_L2TPV2_TYPE_DATA_L, 410 ITEM_L2TPV2_TYPE_DATA_S, 411 ITEM_L2TPV2_TYPE_DATA_O, 412 ITEM_L2TPV2_TYPE_DATA_L_S, 413 ITEM_L2TPV2_TYPE_CTRL, 414 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID, 415 ITEM_L2TPV2_MSG_DATA_SESSION_ID, 416 ITEM_L2TPV2_MSG_DATA_L_LENGTH, 417 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID, 418 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID, 419 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID, 420 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID, 421 ITEM_L2TPV2_MSG_DATA_S_NS, 422 ITEM_L2TPV2_MSG_DATA_S_NR, 423 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID, 424 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID, 425 ITEM_L2TPV2_MSG_DATA_O_OFFSET, 426 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH, 427 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID, 428 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID, 429 ITEM_L2TPV2_MSG_DATA_L_S_NS, 430 ITEM_L2TPV2_MSG_DATA_L_S_NR, 431 ITEM_L2TPV2_MSG_CTRL_LENGTH, 432 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID, 433 ITEM_L2TPV2_MSG_CTRL_SESSION_ID, 434 ITEM_L2TPV2_MSG_CTRL_NS, 435 ITEM_L2TPV2_MSG_CTRL_NR, 436 ITEM_PPP, 437 ITEM_PPP_ADDR, 438 ITEM_PPP_CTRL, 439 ITEM_PPP_PROTO_ID, 440 441 /* Validate/create actions. */ 442 ACTIONS, 443 ACTION_NEXT, 444 ACTION_END, 445 ACTION_VOID, 446 ACTION_PASSTHRU, 447 ACTION_JUMP, 448 ACTION_JUMP_GROUP, 449 ACTION_MARK, 450 ACTION_MARK_ID, 451 ACTION_FLAG, 452 ACTION_QUEUE, 453 ACTION_QUEUE_INDEX, 454 ACTION_DROP, 455 ACTION_COUNT, 456 ACTION_COUNT_ID, 457 ACTION_RSS, 458 ACTION_RSS_FUNC, 459 ACTION_RSS_LEVEL, 460 ACTION_RSS_FUNC_DEFAULT, 461 ACTION_RSS_FUNC_TOEPLITZ, 462 ACTION_RSS_FUNC_SIMPLE_XOR, 463 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ, 464 ACTION_RSS_TYPES, 465 ACTION_RSS_TYPE, 466 ACTION_RSS_KEY, 467 ACTION_RSS_KEY_LEN, 468 ACTION_RSS_QUEUES, 469 ACTION_RSS_QUEUE, 470 ACTION_PF, 471 ACTION_VF, 472 ACTION_VF_ORIGINAL, 473 ACTION_VF_ID, 474 ACTION_PHY_PORT, 475 ACTION_PHY_PORT_ORIGINAL, 476 ACTION_PHY_PORT_INDEX, 477 ACTION_PORT_ID, 478 ACTION_PORT_ID_ORIGINAL, 479 ACTION_PORT_ID_ID, 480 ACTION_METER, 481 ACTION_METER_COLOR, 482 ACTION_METER_COLOR_TYPE, 483 ACTION_METER_COLOR_GREEN, 484 ACTION_METER_COLOR_YELLOW, 485 ACTION_METER_COLOR_RED, 486 ACTION_METER_ID, 487 ACTION_OF_SET_MPLS_TTL, 488 ACTION_OF_SET_MPLS_TTL_MPLS_TTL, 489 ACTION_OF_DEC_MPLS_TTL, 490 ACTION_OF_SET_NW_TTL, 491 ACTION_OF_SET_NW_TTL_NW_TTL, 492 ACTION_OF_DEC_NW_TTL, 493 ACTION_OF_COPY_TTL_OUT, 494 ACTION_OF_COPY_TTL_IN, 495 ACTION_OF_POP_VLAN, 496 ACTION_OF_PUSH_VLAN, 497 ACTION_OF_PUSH_VLAN_ETHERTYPE, 498 ACTION_OF_SET_VLAN_VID, 499 ACTION_OF_SET_VLAN_VID_VLAN_VID, 500 ACTION_OF_SET_VLAN_PCP, 501 ACTION_OF_SET_VLAN_PCP_VLAN_PCP, 502 ACTION_OF_POP_MPLS, 503 ACTION_OF_POP_MPLS_ETHERTYPE, 504 ACTION_OF_PUSH_MPLS, 505 ACTION_OF_PUSH_MPLS_ETHERTYPE, 506 ACTION_VXLAN_ENCAP, 507 ACTION_VXLAN_DECAP, 508 ACTION_NVGRE_ENCAP, 509 ACTION_NVGRE_DECAP, 510 ACTION_L2_ENCAP, 511 ACTION_L2_DECAP, 512 ACTION_MPLSOGRE_ENCAP, 513 ACTION_MPLSOGRE_DECAP, 514 ACTION_MPLSOUDP_ENCAP, 515 ACTION_MPLSOUDP_DECAP, 516 ACTION_SET_IPV4_SRC, 517 ACTION_SET_IPV4_SRC_IPV4_SRC, 518 ACTION_SET_IPV4_DST, 519 ACTION_SET_IPV4_DST_IPV4_DST, 520 ACTION_SET_IPV6_SRC, 521 ACTION_SET_IPV6_SRC_IPV6_SRC, 522 ACTION_SET_IPV6_DST, 523 ACTION_SET_IPV6_DST_IPV6_DST, 524 ACTION_SET_TP_SRC, 525 ACTION_SET_TP_SRC_TP_SRC, 526 ACTION_SET_TP_DST, 527 ACTION_SET_TP_DST_TP_DST, 528 ACTION_MAC_SWAP, 529 ACTION_DEC_TTL, 530 ACTION_SET_TTL, 531 ACTION_SET_TTL_TTL, 532 ACTION_SET_MAC_SRC, 533 ACTION_SET_MAC_SRC_MAC_SRC, 534 ACTION_SET_MAC_DST, 535 ACTION_SET_MAC_DST_MAC_DST, 536 ACTION_INC_TCP_SEQ, 537 ACTION_INC_TCP_SEQ_VALUE, 538 ACTION_DEC_TCP_SEQ, 539 ACTION_DEC_TCP_SEQ_VALUE, 540 ACTION_INC_TCP_ACK, 541 ACTION_INC_TCP_ACK_VALUE, 542 ACTION_DEC_TCP_ACK, 543 ACTION_DEC_TCP_ACK_VALUE, 544 ACTION_RAW_ENCAP, 545 ACTION_RAW_DECAP, 546 ACTION_RAW_ENCAP_INDEX, 547 ACTION_RAW_ENCAP_INDEX_VALUE, 548 ACTION_RAW_DECAP_INDEX, 549 ACTION_RAW_DECAP_INDEX_VALUE, 550 ACTION_SET_TAG, 551 ACTION_SET_TAG_DATA, 552 ACTION_SET_TAG_INDEX, 553 ACTION_SET_TAG_MASK, 554 ACTION_SET_META, 555 ACTION_SET_META_DATA, 556 ACTION_SET_META_MASK, 557 ACTION_SET_IPV4_DSCP, 558 ACTION_SET_IPV4_DSCP_VALUE, 559 ACTION_SET_IPV6_DSCP, 560 ACTION_SET_IPV6_DSCP_VALUE, 561 ACTION_AGE, 562 ACTION_AGE_TIMEOUT, 563 ACTION_SAMPLE, 564 ACTION_SAMPLE_RATIO, 565 ACTION_SAMPLE_INDEX, 566 ACTION_SAMPLE_INDEX_VALUE, 567 ACTION_INDIRECT, 568 INDIRECT_ACTION_ID2PTR, 569 ACTION_MODIFY_FIELD, 570 ACTION_MODIFY_FIELD_OP, 571 ACTION_MODIFY_FIELD_OP_VALUE, 572 ACTION_MODIFY_FIELD_DST_TYPE, 573 ACTION_MODIFY_FIELD_DST_TYPE_VALUE, 574 ACTION_MODIFY_FIELD_DST_LEVEL, 575 ACTION_MODIFY_FIELD_DST_OFFSET, 576 ACTION_MODIFY_FIELD_SRC_TYPE, 577 ACTION_MODIFY_FIELD_SRC_TYPE_VALUE, 578 ACTION_MODIFY_FIELD_SRC_LEVEL, 579 ACTION_MODIFY_FIELD_SRC_OFFSET, 580 ACTION_MODIFY_FIELD_SRC_VALUE, 581 ACTION_MODIFY_FIELD_SRC_POINTER, 582 ACTION_MODIFY_FIELD_WIDTH, 583 ACTION_CONNTRACK, 584 ACTION_CONNTRACK_UPDATE, 585 ACTION_CONNTRACK_UPDATE_DIR, 586 ACTION_CONNTRACK_UPDATE_CTX, 587 ACTION_POL_G, 588 ACTION_POL_Y, 589 ACTION_POL_R, 590 ACTION_PORT_REPRESENTOR, 591 ACTION_PORT_REPRESENTOR_PORT_ID, 592 ACTION_REPRESENTED_PORT, 593 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID, 594 }; 595 596 /** Maximum size for pattern in struct rte_flow_item_raw. */ 597 #define ITEM_RAW_PATTERN_SIZE 512 598 599 /** Maximum size for GENEVE option data pattern in bytes. */ 600 #define ITEM_GENEVE_OPT_DATA_SIZE 124 601 602 /** Storage size for struct rte_flow_item_raw including pattern. */ 603 #define ITEM_RAW_SIZE \ 604 (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE) 605 606 /** Maximum size for external pattern in struct rte_flow_action_modify_data. */ 607 #define ACTION_MODIFY_PATTERN_SIZE 32 608 609 /** Storage size for struct rte_flow_action_modify_field including pattern. */ 610 #define ACTION_MODIFY_SIZE \ 611 (sizeof(struct rte_flow_action_modify_field) + \ 612 ACTION_MODIFY_PATTERN_SIZE) 613 614 /** Maximum number of queue indices in struct rte_flow_action_rss. */ 615 #define ACTION_RSS_QUEUE_NUM 128 616 617 /** Storage for struct rte_flow_action_rss including external data. */ 618 struct action_rss_data { 619 struct rte_flow_action_rss conf; 620 uint8_t key[RSS_HASH_KEY_LENGTH]; 621 uint16_t queue[ACTION_RSS_QUEUE_NUM]; 622 }; 623 624 /** Maximum data size in struct rte_flow_action_raw_encap. */ 625 #define ACTION_RAW_ENCAP_MAX_DATA 512 626 #define RAW_ENCAP_CONFS_MAX_NUM 8 627 628 /** Storage for struct rte_flow_action_raw_encap. */ 629 struct raw_encap_conf { 630 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA]; 631 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA]; 632 size_t size; 633 }; 634 635 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM]; 636 637 /** Storage for struct rte_flow_action_raw_encap including external data. */ 638 struct action_raw_encap_data { 639 struct rte_flow_action_raw_encap conf; 640 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA]; 641 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA]; 642 uint16_t idx; 643 }; 644 645 /** Storage for struct rte_flow_action_raw_decap. */ 646 struct raw_decap_conf { 647 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA]; 648 size_t size; 649 }; 650 651 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM]; 652 653 /** Storage for struct rte_flow_action_raw_decap including external data. */ 654 struct action_raw_decap_data { 655 struct rte_flow_action_raw_decap conf; 656 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA]; 657 uint16_t idx; 658 }; 659 660 struct vxlan_encap_conf vxlan_encap_conf = { 661 .select_ipv4 = 1, 662 .select_vlan = 0, 663 .select_tos_ttl = 0, 664 .vni = "\x00\x00\x00", 665 .udp_src = 0, 666 .udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT), 667 .ipv4_src = RTE_IPV4(127, 0, 0, 1), 668 .ipv4_dst = RTE_IPV4(255, 255, 255, 255), 669 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00" 670 "\x00\x00\x00\x00\x00\x00\x00\x01", 671 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00" 672 "\x00\x00\x00\x00\x00\x00\x11\x11", 673 .vlan_tci = 0, 674 .ip_tos = 0, 675 .ip_ttl = 255, 676 .eth_src = "\x00\x00\x00\x00\x00\x00", 677 .eth_dst = "\xff\xff\xff\xff\xff\xff", 678 }; 679 680 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */ 681 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6 682 683 /** Storage for struct rte_flow_action_vxlan_encap including external data. */ 684 struct action_vxlan_encap_data { 685 struct rte_flow_action_vxlan_encap conf; 686 struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM]; 687 struct rte_flow_item_eth item_eth; 688 struct rte_flow_item_vlan item_vlan; 689 union { 690 struct rte_flow_item_ipv4 item_ipv4; 691 struct rte_flow_item_ipv6 item_ipv6; 692 }; 693 struct rte_flow_item_udp item_udp; 694 struct rte_flow_item_vxlan item_vxlan; 695 }; 696 697 struct nvgre_encap_conf nvgre_encap_conf = { 698 .select_ipv4 = 1, 699 .select_vlan = 0, 700 .tni = "\x00\x00\x00", 701 .ipv4_src = RTE_IPV4(127, 0, 0, 1), 702 .ipv4_dst = RTE_IPV4(255, 255, 255, 255), 703 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00" 704 "\x00\x00\x00\x00\x00\x00\x00\x01", 705 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00" 706 "\x00\x00\x00\x00\x00\x00\x11\x11", 707 .vlan_tci = 0, 708 .eth_src = "\x00\x00\x00\x00\x00\x00", 709 .eth_dst = "\xff\xff\xff\xff\xff\xff", 710 }; 711 712 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */ 713 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5 714 715 /** Storage for struct rte_flow_action_nvgre_encap including external data. */ 716 struct action_nvgre_encap_data { 717 struct rte_flow_action_nvgre_encap conf; 718 struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM]; 719 struct rte_flow_item_eth item_eth; 720 struct rte_flow_item_vlan item_vlan; 721 union { 722 struct rte_flow_item_ipv4 item_ipv4; 723 struct rte_flow_item_ipv6 item_ipv6; 724 }; 725 struct rte_flow_item_nvgre item_nvgre; 726 }; 727 728 struct l2_encap_conf l2_encap_conf; 729 730 struct l2_decap_conf l2_decap_conf; 731 732 struct mplsogre_encap_conf mplsogre_encap_conf; 733 734 struct mplsogre_decap_conf mplsogre_decap_conf; 735 736 struct mplsoudp_encap_conf mplsoudp_encap_conf; 737 738 struct mplsoudp_decap_conf mplsoudp_decap_conf; 739 740 struct rte_flow_action_conntrack conntrack_context; 741 742 #define ACTION_SAMPLE_ACTIONS_NUM 10 743 #define RAW_SAMPLE_CONFS_MAX_NUM 8 744 /** Storage for struct rte_flow_action_sample including external data. */ 745 struct action_sample_data { 746 struct rte_flow_action_sample conf; 747 uint32_t idx; 748 }; 749 /** Storage for struct rte_flow_action_sample. */ 750 struct raw_sample_conf { 751 struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM]; 752 }; 753 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM]; 754 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM]; 755 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM]; 756 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM]; 757 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM]; 758 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM]; 759 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM]; 760 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM]; 761 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM]; 762 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM]; 763 764 static const char *const modify_field_ops[] = { 765 "set", "add", "sub", NULL 766 }; 767 768 static const char *const modify_field_ids[] = { 769 "start", "mac_dst", "mac_src", 770 "vlan_type", "vlan_id", "mac_type", 771 "ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst", 772 "ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst", 773 "tcp_port_src", "tcp_port_dst", 774 "tcp_seq_num", "tcp_ack_num", "tcp_flags", 775 "udp_port_src", "udp_port_dst", 776 "vxlan_vni", "geneve_vni", "gtp_teid", 777 "tag", "mark", "meta", "pointer", "value", NULL 778 }; 779 780 /** Maximum number of subsequent tokens and arguments on the stack. */ 781 #define CTX_STACK_SIZE 16 782 783 /** Parser context. */ 784 struct context { 785 /** Stack of subsequent token lists to process. */ 786 const enum index *next[CTX_STACK_SIZE]; 787 /** Arguments for stacked tokens. */ 788 const void *args[CTX_STACK_SIZE]; 789 enum index curr; /**< Current token index. */ 790 enum index prev; /**< Index of the last token seen. */ 791 int next_num; /**< Number of entries in next[]. */ 792 int args_num; /**< Number of entries in args[]. */ 793 uint32_t eol:1; /**< EOL has been detected. */ 794 uint32_t last:1; /**< No more arguments. */ 795 portid_t port; /**< Current port ID (for completions). */ 796 uint32_t objdata; /**< Object-specific data. */ 797 void *object; /**< Address of current object for relative offsets. */ 798 void *objmask; /**< Object a full mask must be written to. */ 799 }; 800 801 /** Token argument. */ 802 struct arg { 803 uint32_t hton:1; /**< Use network byte ordering. */ 804 uint32_t sign:1; /**< Value is signed. */ 805 uint32_t bounded:1; /**< Value is bounded. */ 806 uintmax_t min; /**< Minimum value if bounded. */ 807 uintmax_t max; /**< Maximum value if bounded. */ 808 uint32_t offset; /**< Relative offset from ctx->object. */ 809 uint32_t size; /**< Field size. */ 810 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */ 811 }; 812 813 /** Parser token definition. */ 814 struct token { 815 /** Type displayed during completion (defaults to "TOKEN"). */ 816 const char *type; 817 /** Help displayed during completion (defaults to token name). */ 818 const char *help; 819 /** Private data used by parser functions. */ 820 const void *priv; 821 /** 822 * Lists of subsequent tokens to push on the stack. Each call to the 823 * parser consumes the last entry of that stack. 824 */ 825 const enum index *const *next; 826 /** Arguments stack for subsequent tokens that need them. */ 827 const struct arg *const *args; 828 /** 829 * Token-processing callback, returns -1 in case of error, the 830 * length of the matched string otherwise. If NULL, attempts to 831 * match the token name. 832 * 833 * If buf is not NULL, the result should be stored in it according 834 * to context. An error is returned if not large enough. 835 */ 836 int (*call)(struct context *ctx, const struct token *token, 837 const char *str, unsigned int len, 838 void *buf, unsigned int size); 839 /** 840 * Callback that provides possible values for this token, used for 841 * completion. Returns -1 in case of error, the number of possible 842 * values otherwise. If NULL, the token name is used. 843 * 844 * If buf is not NULL, entry index ent is written to buf and the 845 * full length of the entry is returned (same behavior as 846 * snprintf()). 847 */ 848 int (*comp)(struct context *ctx, const struct token *token, 849 unsigned int ent, char *buf, unsigned int size); 850 /** Mandatory token name, no default value. */ 851 const char *name; 852 }; 853 854 /** Static initializer for the next field. */ 855 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, } 856 857 /** Static initializer for a NEXT() entry. */ 858 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, } 859 860 /** Static initializer for the args field. */ 861 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, } 862 863 /** Static initializer for ARGS() to target a field. */ 864 #define ARGS_ENTRY(s, f) \ 865 (&(const struct arg){ \ 866 .offset = offsetof(s, f), \ 867 .size = sizeof(((s *)0)->f), \ 868 }) 869 870 /** Static initializer for ARGS() to target a bit-field. */ 871 #define ARGS_ENTRY_BF(s, f, b) \ 872 (&(const struct arg){ \ 873 .size = sizeof(s), \ 874 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \ 875 }) 876 877 /** Static initializer for ARGS() to target a field with limits. */ 878 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \ 879 (&(const struct arg){ \ 880 .bounded = 1, \ 881 .min = (i), \ 882 .max = (a), \ 883 .offset = offsetof(s, f), \ 884 .size = sizeof(((s *)0)->f), \ 885 }) 886 887 /** Static initializer for ARGS() to target an arbitrary bit-mask. */ 888 #define ARGS_ENTRY_MASK(s, f, m) \ 889 (&(const struct arg){ \ 890 .offset = offsetof(s, f), \ 891 .size = sizeof(((s *)0)->f), \ 892 .mask = (const void *)(m), \ 893 }) 894 895 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */ 896 #define ARGS_ENTRY_MASK_HTON(s, f, m) \ 897 (&(const struct arg){ \ 898 .hton = 1, \ 899 .offset = offsetof(s, f), \ 900 .size = sizeof(((s *)0)->f), \ 901 .mask = (const void *)(m), \ 902 }) 903 904 /** Static initializer for ARGS() to target a pointer. */ 905 #define ARGS_ENTRY_PTR(s, f) \ 906 (&(const struct arg){ \ 907 .size = sizeof(*((s *)0)->f), \ 908 }) 909 910 /** Static initializer for ARGS() with arbitrary offset and size. */ 911 #define ARGS_ENTRY_ARB(o, s) \ 912 (&(const struct arg){ \ 913 .offset = (o), \ 914 .size = (s), \ 915 }) 916 917 /** Same as ARGS_ENTRY_ARB() with bounded values. */ 918 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \ 919 (&(const struct arg){ \ 920 .bounded = 1, \ 921 .min = (i), \ 922 .max = (a), \ 923 .offset = (o), \ 924 .size = (s), \ 925 }) 926 927 /** Same as ARGS_ENTRY() using network byte ordering. */ 928 #define ARGS_ENTRY_HTON(s, f) \ 929 (&(const struct arg){ \ 930 .hton = 1, \ 931 .offset = offsetof(s, f), \ 932 .size = sizeof(((s *)0)->f), \ 933 }) 934 935 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */ 936 #define ARG_ENTRY_HTON(s) \ 937 (&(const struct arg){ \ 938 .hton = 1, \ 939 .offset = 0, \ 940 .size = sizeof(s), \ 941 }) 942 943 /** Parser output buffer layout expected by cmd_flow_parsed(). */ 944 struct buffer { 945 enum index command; /**< Flow command. */ 946 portid_t port; /**< Affected port ID. */ 947 queueid_t queue; /** Async queue ID. */ 948 bool postpone; /** Postpone async operation */ 949 union { 950 struct { 951 struct rte_flow_port_attr port_attr; 952 uint32_t nb_queue; 953 struct rte_flow_queue_attr queue_attr; 954 } configure; /**< Configuration arguments. */ 955 struct { 956 uint32_t *template_id; 957 uint32_t template_id_n; 958 } templ_destroy; /**< Template destroy arguments. */ 959 struct { 960 uint32_t id; 961 struct rte_flow_template_table_attr attr; 962 uint32_t *pat_templ_id; 963 uint32_t pat_templ_id_n; 964 uint32_t *act_templ_id; 965 uint32_t act_templ_id_n; 966 } table; /**< Table arguments. */ 967 struct { 968 uint32_t *table_id; 969 uint32_t table_id_n; 970 } table_destroy; /**< Template destroy arguments. */ 971 struct { 972 uint32_t *action_id; 973 uint32_t action_id_n; 974 } ia_destroy; /**< Indirect action destroy arguments. */ 975 struct { 976 uint32_t action_id; 977 } ia; /* Indirect action query arguments */ 978 struct { 979 uint32_t table_id; 980 uint32_t pat_templ_id; 981 uint32_t act_templ_id; 982 struct rte_flow_attr attr; 983 struct tunnel_ops tunnel_ops; 984 struct rte_flow_item *pattern; 985 struct rte_flow_action *actions; 986 struct rte_flow_action *masks; 987 uint32_t pattern_n; 988 uint32_t actions_n; 989 uint8_t *data; 990 } vc; /**< Validate/create arguments. */ 991 struct { 992 uint32_t *rule; 993 uint32_t rule_n; 994 } destroy; /**< Destroy arguments. */ 995 struct { 996 char file[128]; 997 bool mode; 998 uint32_t rule; 999 } dump; /**< Dump arguments. */ 1000 struct { 1001 uint32_t rule; 1002 struct rte_flow_action action; 1003 } query; /**< Query arguments. */ 1004 struct { 1005 uint32_t *group; 1006 uint32_t group_n; 1007 } list; /**< List arguments. */ 1008 struct { 1009 int set; 1010 } isolate; /**< Isolated mode arguments. */ 1011 struct { 1012 int destroy; 1013 } aged; /**< Aged arguments. */ 1014 struct { 1015 uint32_t policy_id; 1016 } policy;/**< Policy arguments. */ 1017 struct { 1018 uint16_t token; 1019 uintptr_t uintptr; 1020 char filename[128]; 1021 } flex; /**< Flex arguments*/ 1022 } args; /**< Command arguments. */ 1023 }; 1024 1025 /** Private data for pattern items. */ 1026 struct parse_item_priv { 1027 enum rte_flow_item_type type; /**< Item type. */ 1028 uint32_t size; /**< Size of item specification structure. */ 1029 }; 1030 1031 #define PRIV_ITEM(t, s) \ 1032 (&(const struct parse_item_priv){ \ 1033 .type = RTE_FLOW_ITEM_TYPE_ ## t, \ 1034 .size = s, \ 1035 }) 1036 1037 /** Private data for actions. */ 1038 struct parse_action_priv { 1039 enum rte_flow_action_type type; /**< Action type. */ 1040 uint32_t size; /**< Size of action configuration structure. */ 1041 }; 1042 1043 #define PRIV_ACTION(t, s) \ 1044 (&(const struct parse_action_priv){ \ 1045 .type = RTE_FLOW_ACTION_TYPE_ ## t, \ 1046 .size = s, \ 1047 }) 1048 1049 static const enum index next_flex_item[] = { 1050 FLEX_ITEM_INIT, 1051 FLEX_ITEM_CREATE, 1052 FLEX_ITEM_DESTROY, 1053 ZERO, 1054 }; 1055 1056 static const enum index next_config_attr[] = { 1057 CONFIG_QUEUES_NUMBER, 1058 CONFIG_QUEUES_SIZE, 1059 CONFIG_COUNTERS_NUMBER, 1060 CONFIG_AGING_OBJECTS_NUMBER, 1061 CONFIG_METERS_NUMBER, 1062 END, 1063 ZERO, 1064 }; 1065 1066 static const enum index next_pt_subcmd[] = { 1067 PATTERN_TEMPLATE_CREATE, 1068 PATTERN_TEMPLATE_DESTROY, 1069 ZERO, 1070 }; 1071 1072 static const enum index next_pt_attr[] = { 1073 PATTERN_TEMPLATE_CREATE_ID, 1074 PATTERN_TEMPLATE_RELAXED_MATCHING, 1075 PATTERN_TEMPLATE_INGRESS, 1076 PATTERN_TEMPLATE_EGRESS, 1077 PATTERN_TEMPLATE_TRANSFER, 1078 PATTERN_TEMPLATE_SPEC, 1079 ZERO, 1080 }; 1081 1082 static const enum index next_pt_destroy_attr[] = { 1083 PATTERN_TEMPLATE_DESTROY_ID, 1084 END, 1085 ZERO, 1086 }; 1087 1088 static const enum index next_at_subcmd[] = { 1089 ACTIONS_TEMPLATE_CREATE, 1090 ACTIONS_TEMPLATE_DESTROY, 1091 ZERO, 1092 }; 1093 1094 static const enum index next_at_attr[] = { 1095 ACTIONS_TEMPLATE_CREATE_ID, 1096 ACTIONS_TEMPLATE_INGRESS, 1097 ACTIONS_TEMPLATE_EGRESS, 1098 ACTIONS_TEMPLATE_TRANSFER, 1099 ACTIONS_TEMPLATE_SPEC, 1100 ZERO, 1101 }; 1102 1103 static const enum index next_at_destroy_attr[] = { 1104 ACTIONS_TEMPLATE_DESTROY_ID, 1105 END, 1106 ZERO, 1107 }; 1108 1109 static const enum index next_table_subcmd[] = { 1110 TABLE_CREATE, 1111 TABLE_DESTROY, 1112 ZERO, 1113 }; 1114 1115 static const enum index next_table_attr[] = { 1116 TABLE_CREATE_ID, 1117 TABLE_GROUP, 1118 TABLE_PRIORITY, 1119 TABLE_INGRESS, 1120 TABLE_EGRESS, 1121 TABLE_TRANSFER, 1122 TABLE_RULES_NUMBER, 1123 TABLE_PATTERN_TEMPLATE, 1124 TABLE_ACTIONS_TEMPLATE, 1125 END, 1126 ZERO, 1127 }; 1128 1129 static const enum index next_table_destroy_attr[] = { 1130 TABLE_DESTROY_ID, 1131 END, 1132 ZERO, 1133 }; 1134 1135 static const enum index next_queue_subcmd[] = { 1136 QUEUE_CREATE, 1137 QUEUE_DESTROY, 1138 ZERO, 1139 }; 1140 1141 static const enum index next_queue_destroy_attr[] = { 1142 QUEUE_DESTROY_ID, 1143 END, 1144 ZERO, 1145 }; 1146 1147 static const enum index next_ia_create_attr[] = { 1148 INDIRECT_ACTION_CREATE_ID, 1149 INDIRECT_ACTION_INGRESS, 1150 INDIRECT_ACTION_EGRESS, 1151 INDIRECT_ACTION_TRANSFER, 1152 INDIRECT_ACTION_SPEC, 1153 ZERO, 1154 }; 1155 1156 static const enum index next_dump_subcmd[] = { 1157 DUMP_ALL, 1158 DUMP_ONE, 1159 ZERO, 1160 }; 1161 1162 static const enum index next_ia_subcmd[] = { 1163 INDIRECT_ACTION_CREATE, 1164 INDIRECT_ACTION_UPDATE, 1165 INDIRECT_ACTION_DESTROY, 1166 INDIRECT_ACTION_QUERY, 1167 ZERO, 1168 }; 1169 1170 static const enum index next_vc_attr[] = { 1171 VC_GROUP, 1172 VC_PRIORITY, 1173 VC_INGRESS, 1174 VC_EGRESS, 1175 VC_TRANSFER, 1176 VC_TUNNEL_SET, 1177 VC_TUNNEL_MATCH, 1178 ITEM_PATTERN, 1179 ZERO, 1180 }; 1181 1182 static const enum index next_destroy_attr[] = { 1183 DESTROY_RULE, 1184 END, 1185 ZERO, 1186 }; 1187 1188 static const enum index next_dump_attr[] = { 1189 COMMON_FILE_PATH, 1190 END, 1191 ZERO, 1192 }; 1193 1194 static const enum index next_list_attr[] = { 1195 LIST_GROUP, 1196 END, 1197 ZERO, 1198 }; 1199 1200 static const enum index next_aged_attr[] = { 1201 AGED_DESTROY, 1202 END, 1203 ZERO, 1204 }; 1205 1206 static const enum index next_ia_destroy_attr[] = { 1207 INDIRECT_ACTION_DESTROY_ID, 1208 END, 1209 ZERO, 1210 }; 1211 1212 static const enum index item_param[] = { 1213 ITEM_PARAM_IS, 1214 ITEM_PARAM_SPEC, 1215 ITEM_PARAM_LAST, 1216 ITEM_PARAM_MASK, 1217 ITEM_PARAM_PREFIX, 1218 ZERO, 1219 }; 1220 1221 static const enum index next_item[] = { 1222 ITEM_END, 1223 ITEM_VOID, 1224 ITEM_INVERT, 1225 ITEM_ANY, 1226 ITEM_PF, 1227 ITEM_VF, 1228 ITEM_PHY_PORT, 1229 ITEM_PORT_ID, 1230 ITEM_MARK, 1231 ITEM_RAW, 1232 ITEM_ETH, 1233 ITEM_VLAN, 1234 ITEM_IPV4, 1235 ITEM_IPV6, 1236 ITEM_ICMP, 1237 ITEM_UDP, 1238 ITEM_TCP, 1239 ITEM_SCTP, 1240 ITEM_VXLAN, 1241 ITEM_E_TAG, 1242 ITEM_NVGRE, 1243 ITEM_MPLS, 1244 ITEM_GRE, 1245 ITEM_FUZZY, 1246 ITEM_GTP, 1247 ITEM_GTPC, 1248 ITEM_GTPU, 1249 ITEM_GENEVE, 1250 ITEM_VXLAN_GPE, 1251 ITEM_ARP_ETH_IPV4, 1252 ITEM_IPV6_EXT, 1253 ITEM_IPV6_FRAG_EXT, 1254 ITEM_ICMP6, 1255 ITEM_ICMP6_ND_NS, 1256 ITEM_ICMP6_ND_NA, 1257 ITEM_ICMP6_ND_OPT, 1258 ITEM_ICMP6_ND_OPT_SLA_ETH, 1259 ITEM_ICMP6_ND_OPT_TLA_ETH, 1260 ITEM_META, 1261 ITEM_GRE_KEY, 1262 ITEM_GRE_OPTION, 1263 ITEM_GTP_PSC, 1264 ITEM_PPPOES, 1265 ITEM_PPPOED, 1266 ITEM_PPPOE_PROTO_ID, 1267 ITEM_HIGIG2, 1268 ITEM_TAG, 1269 ITEM_L2TPV3OIP, 1270 ITEM_ESP, 1271 ITEM_AH, 1272 ITEM_PFCP, 1273 ITEM_ECPRI, 1274 ITEM_GENEVE_OPT, 1275 ITEM_INTEGRITY, 1276 ITEM_CONNTRACK, 1277 ITEM_PORT_REPRESENTOR, 1278 ITEM_REPRESENTED_PORT, 1279 ITEM_FLEX, 1280 ITEM_L2TPV2, 1281 ITEM_PPP, 1282 END_SET, 1283 ZERO, 1284 }; 1285 1286 static const enum index item_fuzzy[] = { 1287 ITEM_FUZZY_THRESH, 1288 ITEM_NEXT, 1289 ZERO, 1290 }; 1291 1292 static const enum index item_any[] = { 1293 ITEM_ANY_NUM, 1294 ITEM_NEXT, 1295 ZERO, 1296 }; 1297 1298 static const enum index item_vf[] = { 1299 ITEM_VF_ID, 1300 ITEM_NEXT, 1301 ZERO, 1302 }; 1303 1304 static const enum index item_phy_port[] = { 1305 ITEM_PHY_PORT_INDEX, 1306 ITEM_NEXT, 1307 ZERO, 1308 }; 1309 1310 static const enum index item_port_id[] = { 1311 ITEM_PORT_ID_ID, 1312 ITEM_NEXT, 1313 ZERO, 1314 }; 1315 1316 static const enum index item_mark[] = { 1317 ITEM_MARK_ID, 1318 ITEM_NEXT, 1319 ZERO, 1320 }; 1321 1322 static const enum index item_raw[] = { 1323 ITEM_RAW_RELATIVE, 1324 ITEM_RAW_SEARCH, 1325 ITEM_RAW_OFFSET, 1326 ITEM_RAW_LIMIT, 1327 ITEM_RAW_PATTERN, 1328 ITEM_RAW_PATTERN_HEX, 1329 ITEM_NEXT, 1330 ZERO, 1331 }; 1332 1333 static const enum index item_eth[] = { 1334 ITEM_ETH_DST, 1335 ITEM_ETH_SRC, 1336 ITEM_ETH_TYPE, 1337 ITEM_ETH_HAS_VLAN, 1338 ITEM_NEXT, 1339 ZERO, 1340 }; 1341 1342 static const enum index item_vlan[] = { 1343 ITEM_VLAN_TCI, 1344 ITEM_VLAN_PCP, 1345 ITEM_VLAN_DEI, 1346 ITEM_VLAN_VID, 1347 ITEM_VLAN_INNER_TYPE, 1348 ITEM_VLAN_HAS_MORE_VLAN, 1349 ITEM_NEXT, 1350 ZERO, 1351 }; 1352 1353 static const enum index item_ipv4[] = { 1354 ITEM_IPV4_VER_IHL, 1355 ITEM_IPV4_TOS, 1356 ITEM_IPV4_ID, 1357 ITEM_IPV4_FRAGMENT_OFFSET, 1358 ITEM_IPV4_TTL, 1359 ITEM_IPV4_PROTO, 1360 ITEM_IPV4_SRC, 1361 ITEM_IPV4_DST, 1362 ITEM_NEXT, 1363 ZERO, 1364 }; 1365 1366 static const enum index item_ipv6[] = { 1367 ITEM_IPV6_TC, 1368 ITEM_IPV6_FLOW, 1369 ITEM_IPV6_PROTO, 1370 ITEM_IPV6_HOP, 1371 ITEM_IPV6_SRC, 1372 ITEM_IPV6_DST, 1373 ITEM_IPV6_HAS_FRAG_EXT, 1374 ITEM_NEXT, 1375 ZERO, 1376 }; 1377 1378 static const enum index item_icmp[] = { 1379 ITEM_ICMP_TYPE, 1380 ITEM_ICMP_CODE, 1381 ITEM_ICMP_IDENT, 1382 ITEM_ICMP_SEQ, 1383 ITEM_NEXT, 1384 ZERO, 1385 }; 1386 1387 static const enum index item_udp[] = { 1388 ITEM_UDP_SRC, 1389 ITEM_UDP_DST, 1390 ITEM_NEXT, 1391 ZERO, 1392 }; 1393 1394 static const enum index item_tcp[] = { 1395 ITEM_TCP_SRC, 1396 ITEM_TCP_DST, 1397 ITEM_TCP_FLAGS, 1398 ITEM_NEXT, 1399 ZERO, 1400 }; 1401 1402 static const enum index item_sctp[] = { 1403 ITEM_SCTP_SRC, 1404 ITEM_SCTP_DST, 1405 ITEM_SCTP_TAG, 1406 ITEM_SCTP_CKSUM, 1407 ITEM_NEXT, 1408 ZERO, 1409 }; 1410 1411 static const enum index item_vxlan[] = { 1412 ITEM_VXLAN_VNI, 1413 ITEM_VXLAN_LAST_RSVD, 1414 ITEM_NEXT, 1415 ZERO, 1416 }; 1417 1418 static const enum index item_e_tag[] = { 1419 ITEM_E_TAG_GRP_ECID_B, 1420 ITEM_NEXT, 1421 ZERO, 1422 }; 1423 1424 static const enum index item_nvgre[] = { 1425 ITEM_NVGRE_TNI, 1426 ITEM_NEXT, 1427 ZERO, 1428 }; 1429 1430 static const enum index item_mpls[] = { 1431 ITEM_MPLS_LABEL, 1432 ITEM_MPLS_TC, 1433 ITEM_MPLS_S, 1434 ITEM_NEXT, 1435 ZERO, 1436 }; 1437 1438 static const enum index item_gre[] = { 1439 ITEM_GRE_PROTO, 1440 ITEM_GRE_C_RSVD0_VER, 1441 ITEM_GRE_C_BIT, 1442 ITEM_GRE_K_BIT, 1443 ITEM_GRE_S_BIT, 1444 ITEM_NEXT, 1445 ZERO, 1446 }; 1447 1448 static const enum index item_gre_key[] = { 1449 ITEM_GRE_KEY_VALUE, 1450 ITEM_NEXT, 1451 ZERO, 1452 }; 1453 1454 static const enum index item_gre_option[] = { 1455 ITEM_GRE_OPTION_CHECKSUM, 1456 ITEM_GRE_OPTION_KEY, 1457 ITEM_GRE_OPTION_SEQUENCE, 1458 ITEM_NEXT, 1459 ZERO, 1460 }; 1461 1462 static const enum index item_gtp[] = { 1463 ITEM_GTP_FLAGS, 1464 ITEM_GTP_MSG_TYPE, 1465 ITEM_GTP_TEID, 1466 ITEM_NEXT, 1467 ZERO, 1468 }; 1469 1470 static const enum index item_geneve[] = { 1471 ITEM_GENEVE_VNI, 1472 ITEM_GENEVE_PROTO, 1473 ITEM_GENEVE_OPTLEN, 1474 ITEM_NEXT, 1475 ZERO, 1476 }; 1477 1478 static const enum index item_vxlan_gpe[] = { 1479 ITEM_VXLAN_GPE_VNI, 1480 ITEM_NEXT, 1481 ZERO, 1482 }; 1483 1484 static const enum index item_arp_eth_ipv4[] = { 1485 ITEM_ARP_ETH_IPV4_SHA, 1486 ITEM_ARP_ETH_IPV4_SPA, 1487 ITEM_ARP_ETH_IPV4_THA, 1488 ITEM_ARP_ETH_IPV4_TPA, 1489 ITEM_NEXT, 1490 ZERO, 1491 }; 1492 1493 static const enum index item_ipv6_ext[] = { 1494 ITEM_IPV6_EXT_NEXT_HDR, 1495 ITEM_NEXT, 1496 ZERO, 1497 }; 1498 1499 static const enum index item_ipv6_frag_ext[] = { 1500 ITEM_IPV6_FRAG_EXT_NEXT_HDR, 1501 ITEM_IPV6_FRAG_EXT_FRAG_DATA, 1502 ITEM_IPV6_FRAG_EXT_ID, 1503 ITEM_NEXT, 1504 ZERO, 1505 }; 1506 1507 static const enum index item_icmp6[] = { 1508 ITEM_ICMP6_TYPE, 1509 ITEM_ICMP6_CODE, 1510 ITEM_NEXT, 1511 ZERO, 1512 }; 1513 1514 static const enum index item_icmp6_nd_ns[] = { 1515 ITEM_ICMP6_ND_NS_TARGET_ADDR, 1516 ITEM_NEXT, 1517 ZERO, 1518 }; 1519 1520 static const enum index item_icmp6_nd_na[] = { 1521 ITEM_ICMP6_ND_NA_TARGET_ADDR, 1522 ITEM_NEXT, 1523 ZERO, 1524 }; 1525 1526 static const enum index item_icmp6_nd_opt[] = { 1527 ITEM_ICMP6_ND_OPT_TYPE, 1528 ITEM_NEXT, 1529 ZERO, 1530 }; 1531 1532 static const enum index item_icmp6_nd_opt_sla_eth[] = { 1533 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA, 1534 ITEM_NEXT, 1535 ZERO, 1536 }; 1537 1538 static const enum index item_icmp6_nd_opt_tla_eth[] = { 1539 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA, 1540 ITEM_NEXT, 1541 ZERO, 1542 }; 1543 1544 static const enum index item_meta[] = { 1545 ITEM_META_DATA, 1546 ITEM_NEXT, 1547 ZERO, 1548 }; 1549 1550 static const enum index item_gtp_psc[] = { 1551 ITEM_GTP_PSC_QFI, 1552 ITEM_GTP_PSC_PDU_T, 1553 ITEM_NEXT, 1554 ZERO, 1555 }; 1556 1557 static const enum index item_pppoed[] = { 1558 ITEM_PPPOE_SEID, 1559 ITEM_NEXT, 1560 ZERO, 1561 }; 1562 1563 static const enum index item_pppoes[] = { 1564 ITEM_PPPOE_SEID, 1565 ITEM_NEXT, 1566 ZERO, 1567 }; 1568 1569 static const enum index item_pppoe_proto_id[] = { 1570 ITEM_NEXT, 1571 ZERO, 1572 }; 1573 1574 static const enum index item_higig2[] = { 1575 ITEM_HIGIG2_CLASSIFICATION, 1576 ITEM_HIGIG2_VID, 1577 ITEM_NEXT, 1578 ZERO, 1579 }; 1580 1581 static const enum index item_esp[] = { 1582 ITEM_ESP_SPI, 1583 ITEM_NEXT, 1584 ZERO, 1585 }; 1586 1587 static const enum index item_ah[] = { 1588 ITEM_AH_SPI, 1589 ITEM_NEXT, 1590 ZERO, 1591 }; 1592 1593 static const enum index item_pfcp[] = { 1594 ITEM_PFCP_S_FIELD, 1595 ITEM_PFCP_SEID, 1596 ITEM_NEXT, 1597 ZERO, 1598 }; 1599 1600 static const enum index next_set_raw[] = { 1601 SET_RAW_INDEX, 1602 ITEM_ETH, 1603 ZERO, 1604 }; 1605 1606 static const enum index item_tag[] = { 1607 ITEM_TAG_DATA, 1608 ITEM_TAG_INDEX, 1609 ITEM_NEXT, 1610 ZERO, 1611 }; 1612 1613 static const enum index item_l2tpv3oip[] = { 1614 ITEM_L2TPV3OIP_SESSION_ID, 1615 ITEM_NEXT, 1616 ZERO, 1617 }; 1618 1619 static const enum index item_ecpri[] = { 1620 ITEM_ECPRI_COMMON, 1621 ITEM_NEXT, 1622 ZERO, 1623 }; 1624 1625 static const enum index item_ecpri_common[] = { 1626 ITEM_ECPRI_COMMON_TYPE, 1627 ZERO, 1628 }; 1629 1630 static const enum index item_ecpri_common_type[] = { 1631 ITEM_ECPRI_COMMON_TYPE_IQ_DATA, 1632 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL, 1633 ITEM_ECPRI_COMMON_TYPE_DLY_MSR, 1634 ZERO, 1635 }; 1636 1637 static const enum index item_geneve_opt[] = { 1638 ITEM_GENEVE_OPT_CLASS, 1639 ITEM_GENEVE_OPT_TYPE, 1640 ITEM_GENEVE_OPT_LENGTH, 1641 ITEM_GENEVE_OPT_DATA, 1642 ITEM_NEXT, 1643 ZERO, 1644 }; 1645 1646 static const enum index item_integrity[] = { 1647 ITEM_INTEGRITY_LEVEL, 1648 ITEM_INTEGRITY_VALUE, 1649 ZERO, 1650 }; 1651 1652 static const enum index item_integrity_lv[] = { 1653 ITEM_INTEGRITY_LEVEL, 1654 ITEM_INTEGRITY_VALUE, 1655 ITEM_NEXT, 1656 ZERO, 1657 }; 1658 1659 static const enum index item_port_representor[] = { 1660 ITEM_PORT_REPRESENTOR_PORT_ID, 1661 ITEM_NEXT, 1662 ZERO, 1663 }; 1664 1665 static const enum index item_represented_port[] = { 1666 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID, 1667 ITEM_NEXT, 1668 ZERO, 1669 }; 1670 1671 static const enum index item_flex[] = { 1672 ITEM_FLEX_PATTERN_HANDLE, 1673 ITEM_FLEX_ITEM_HANDLE, 1674 ITEM_NEXT, 1675 ZERO, 1676 }; 1677 1678 static const enum index item_l2tpv2[] = { 1679 ITEM_L2TPV2_TYPE, 1680 ITEM_NEXT, 1681 ZERO, 1682 }; 1683 1684 static const enum index item_l2tpv2_type[] = { 1685 ITEM_L2TPV2_TYPE_DATA, 1686 ITEM_L2TPV2_TYPE_DATA_L, 1687 ITEM_L2TPV2_TYPE_DATA_S, 1688 ITEM_L2TPV2_TYPE_DATA_O, 1689 ITEM_L2TPV2_TYPE_DATA_L_S, 1690 ITEM_L2TPV2_TYPE_CTRL, 1691 ZERO, 1692 }; 1693 1694 static const enum index item_l2tpv2_type_data[] = { 1695 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID, 1696 ITEM_L2TPV2_MSG_DATA_SESSION_ID, 1697 ITEM_NEXT, 1698 ZERO, 1699 }; 1700 1701 static const enum index item_l2tpv2_type_data_l[] = { 1702 ITEM_L2TPV2_MSG_DATA_L_LENGTH, 1703 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID, 1704 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID, 1705 ITEM_NEXT, 1706 ZERO, 1707 }; 1708 1709 static const enum index item_l2tpv2_type_data_s[] = { 1710 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID, 1711 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID, 1712 ITEM_L2TPV2_MSG_DATA_S_NS, 1713 ITEM_L2TPV2_MSG_DATA_S_NR, 1714 ITEM_NEXT, 1715 ZERO, 1716 }; 1717 1718 static const enum index item_l2tpv2_type_data_o[] = { 1719 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID, 1720 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID, 1721 ITEM_L2TPV2_MSG_DATA_O_OFFSET, 1722 ITEM_NEXT, 1723 ZERO, 1724 }; 1725 1726 static const enum index item_l2tpv2_type_data_l_s[] = { 1727 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH, 1728 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID, 1729 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID, 1730 ITEM_L2TPV2_MSG_DATA_L_S_NS, 1731 ITEM_L2TPV2_MSG_DATA_L_S_NR, 1732 ITEM_NEXT, 1733 ZERO, 1734 }; 1735 1736 static const enum index item_l2tpv2_type_ctrl[] = { 1737 ITEM_L2TPV2_MSG_CTRL_LENGTH, 1738 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID, 1739 ITEM_L2TPV2_MSG_CTRL_SESSION_ID, 1740 ITEM_L2TPV2_MSG_CTRL_NS, 1741 ITEM_L2TPV2_MSG_CTRL_NR, 1742 ITEM_NEXT, 1743 ZERO, 1744 }; 1745 1746 static const enum index item_ppp[] = { 1747 ITEM_PPP_ADDR, 1748 ITEM_PPP_CTRL, 1749 ITEM_PPP_PROTO_ID, 1750 ITEM_NEXT, 1751 ZERO, 1752 }; 1753 1754 static const enum index next_action[] = { 1755 ACTION_END, 1756 ACTION_VOID, 1757 ACTION_PASSTHRU, 1758 ACTION_JUMP, 1759 ACTION_MARK, 1760 ACTION_FLAG, 1761 ACTION_QUEUE, 1762 ACTION_DROP, 1763 ACTION_COUNT, 1764 ACTION_RSS, 1765 ACTION_PF, 1766 ACTION_VF, 1767 ACTION_PHY_PORT, 1768 ACTION_PORT_ID, 1769 ACTION_METER, 1770 ACTION_METER_COLOR, 1771 ACTION_OF_SET_MPLS_TTL, 1772 ACTION_OF_DEC_MPLS_TTL, 1773 ACTION_OF_SET_NW_TTL, 1774 ACTION_OF_DEC_NW_TTL, 1775 ACTION_OF_COPY_TTL_OUT, 1776 ACTION_OF_COPY_TTL_IN, 1777 ACTION_OF_POP_VLAN, 1778 ACTION_OF_PUSH_VLAN, 1779 ACTION_OF_SET_VLAN_VID, 1780 ACTION_OF_SET_VLAN_PCP, 1781 ACTION_OF_POP_MPLS, 1782 ACTION_OF_PUSH_MPLS, 1783 ACTION_VXLAN_ENCAP, 1784 ACTION_VXLAN_DECAP, 1785 ACTION_NVGRE_ENCAP, 1786 ACTION_NVGRE_DECAP, 1787 ACTION_L2_ENCAP, 1788 ACTION_L2_DECAP, 1789 ACTION_MPLSOGRE_ENCAP, 1790 ACTION_MPLSOGRE_DECAP, 1791 ACTION_MPLSOUDP_ENCAP, 1792 ACTION_MPLSOUDP_DECAP, 1793 ACTION_SET_IPV4_SRC, 1794 ACTION_SET_IPV4_DST, 1795 ACTION_SET_IPV6_SRC, 1796 ACTION_SET_IPV6_DST, 1797 ACTION_SET_TP_SRC, 1798 ACTION_SET_TP_DST, 1799 ACTION_MAC_SWAP, 1800 ACTION_DEC_TTL, 1801 ACTION_SET_TTL, 1802 ACTION_SET_MAC_SRC, 1803 ACTION_SET_MAC_DST, 1804 ACTION_INC_TCP_SEQ, 1805 ACTION_DEC_TCP_SEQ, 1806 ACTION_INC_TCP_ACK, 1807 ACTION_DEC_TCP_ACK, 1808 ACTION_RAW_ENCAP, 1809 ACTION_RAW_DECAP, 1810 ACTION_SET_TAG, 1811 ACTION_SET_META, 1812 ACTION_SET_IPV4_DSCP, 1813 ACTION_SET_IPV6_DSCP, 1814 ACTION_AGE, 1815 ACTION_SAMPLE, 1816 ACTION_INDIRECT, 1817 ACTION_MODIFY_FIELD, 1818 ACTION_CONNTRACK, 1819 ACTION_CONNTRACK_UPDATE, 1820 ACTION_PORT_REPRESENTOR, 1821 ACTION_REPRESENTED_PORT, 1822 ZERO, 1823 }; 1824 1825 static const enum index action_mark[] = { 1826 ACTION_MARK_ID, 1827 ACTION_NEXT, 1828 ZERO, 1829 }; 1830 1831 static const enum index action_queue[] = { 1832 ACTION_QUEUE_INDEX, 1833 ACTION_NEXT, 1834 ZERO, 1835 }; 1836 1837 static const enum index action_count[] = { 1838 ACTION_COUNT_ID, 1839 ACTION_NEXT, 1840 ZERO, 1841 }; 1842 1843 static const enum index action_rss[] = { 1844 ACTION_RSS_FUNC, 1845 ACTION_RSS_LEVEL, 1846 ACTION_RSS_TYPES, 1847 ACTION_RSS_KEY, 1848 ACTION_RSS_KEY_LEN, 1849 ACTION_RSS_QUEUES, 1850 ACTION_NEXT, 1851 ZERO, 1852 }; 1853 1854 static const enum index action_vf[] = { 1855 ACTION_VF_ORIGINAL, 1856 ACTION_VF_ID, 1857 ACTION_NEXT, 1858 ZERO, 1859 }; 1860 1861 static const enum index action_phy_port[] = { 1862 ACTION_PHY_PORT_ORIGINAL, 1863 ACTION_PHY_PORT_INDEX, 1864 ACTION_NEXT, 1865 ZERO, 1866 }; 1867 1868 static const enum index action_port_id[] = { 1869 ACTION_PORT_ID_ORIGINAL, 1870 ACTION_PORT_ID_ID, 1871 ACTION_NEXT, 1872 ZERO, 1873 }; 1874 1875 static const enum index action_meter[] = { 1876 ACTION_METER_ID, 1877 ACTION_NEXT, 1878 ZERO, 1879 }; 1880 1881 static const enum index action_meter_color[] = { 1882 ACTION_METER_COLOR_TYPE, 1883 ACTION_NEXT, 1884 ZERO, 1885 }; 1886 1887 static const enum index action_of_set_mpls_ttl[] = { 1888 ACTION_OF_SET_MPLS_TTL_MPLS_TTL, 1889 ACTION_NEXT, 1890 ZERO, 1891 }; 1892 1893 static const enum index action_of_set_nw_ttl[] = { 1894 ACTION_OF_SET_NW_TTL_NW_TTL, 1895 ACTION_NEXT, 1896 ZERO, 1897 }; 1898 1899 static const enum index action_of_push_vlan[] = { 1900 ACTION_OF_PUSH_VLAN_ETHERTYPE, 1901 ACTION_NEXT, 1902 ZERO, 1903 }; 1904 1905 static const enum index action_of_set_vlan_vid[] = { 1906 ACTION_OF_SET_VLAN_VID_VLAN_VID, 1907 ACTION_NEXT, 1908 ZERO, 1909 }; 1910 1911 static const enum index action_of_set_vlan_pcp[] = { 1912 ACTION_OF_SET_VLAN_PCP_VLAN_PCP, 1913 ACTION_NEXT, 1914 ZERO, 1915 }; 1916 1917 static const enum index action_of_pop_mpls[] = { 1918 ACTION_OF_POP_MPLS_ETHERTYPE, 1919 ACTION_NEXT, 1920 ZERO, 1921 }; 1922 1923 static const enum index action_of_push_mpls[] = { 1924 ACTION_OF_PUSH_MPLS_ETHERTYPE, 1925 ACTION_NEXT, 1926 ZERO, 1927 }; 1928 1929 static const enum index action_set_ipv4_src[] = { 1930 ACTION_SET_IPV4_SRC_IPV4_SRC, 1931 ACTION_NEXT, 1932 ZERO, 1933 }; 1934 1935 static const enum index action_set_mac_src[] = { 1936 ACTION_SET_MAC_SRC_MAC_SRC, 1937 ACTION_NEXT, 1938 ZERO, 1939 }; 1940 1941 static const enum index action_set_ipv4_dst[] = { 1942 ACTION_SET_IPV4_DST_IPV4_DST, 1943 ACTION_NEXT, 1944 ZERO, 1945 }; 1946 1947 static const enum index action_set_ipv6_src[] = { 1948 ACTION_SET_IPV6_SRC_IPV6_SRC, 1949 ACTION_NEXT, 1950 ZERO, 1951 }; 1952 1953 static const enum index action_set_ipv6_dst[] = { 1954 ACTION_SET_IPV6_DST_IPV6_DST, 1955 ACTION_NEXT, 1956 ZERO, 1957 }; 1958 1959 static const enum index action_set_tp_src[] = { 1960 ACTION_SET_TP_SRC_TP_SRC, 1961 ACTION_NEXT, 1962 ZERO, 1963 }; 1964 1965 static const enum index action_set_tp_dst[] = { 1966 ACTION_SET_TP_DST_TP_DST, 1967 ACTION_NEXT, 1968 ZERO, 1969 }; 1970 1971 static const enum index action_set_ttl[] = { 1972 ACTION_SET_TTL_TTL, 1973 ACTION_NEXT, 1974 ZERO, 1975 }; 1976 1977 static const enum index action_jump[] = { 1978 ACTION_JUMP_GROUP, 1979 ACTION_NEXT, 1980 ZERO, 1981 }; 1982 1983 static const enum index action_set_mac_dst[] = { 1984 ACTION_SET_MAC_DST_MAC_DST, 1985 ACTION_NEXT, 1986 ZERO, 1987 }; 1988 1989 static const enum index action_inc_tcp_seq[] = { 1990 ACTION_INC_TCP_SEQ_VALUE, 1991 ACTION_NEXT, 1992 ZERO, 1993 }; 1994 1995 static const enum index action_dec_tcp_seq[] = { 1996 ACTION_DEC_TCP_SEQ_VALUE, 1997 ACTION_NEXT, 1998 ZERO, 1999 }; 2000 2001 static const enum index action_inc_tcp_ack[] = { 2002 ACTION_INC_TCP_ACK_VALUE, 2003 ACTION_NEXT, 2004 ZERO, 2005 }; 2006 2007 static const enum index action_dec_tcp_ack[] = { 2008 ACTION_DEC_TCP_ACK_VALUE, 2009 ACTION_NEXT, 2010 ZERO, 2011 }; 2012 2013 static const enum index action_raw_encap[] = { 2014 ACTION_RAW_ENCAP_INDEX, 2015 ACTION_NEXT, 2016 ZERO, 2017 }; 2018 2019 static const enum index action_raw_decap[] = { 2020 ACTION_RAW_DECAP_INDEX, 2021 ACTION_NEXT, 2022 ZERO, 2023 }; 2024 2025 static const enum index action_set_tag[] = { 2026 ACTION_SET_TAG_DATA, 2027 ACTION_SET_TAG_INDEX, 2028 ACTION_SET_TAG_MASK, 2029 ACTION_NEXT, 2030 ZERO, 2031 }; 2032 2033 static const enum index action_set_meta[] = { 2034 ACTION_SET_META_DATA, 2035 ACTION_SET_META_MASK, 2036 ACTION_NEXT, 2037 ZERO, 2038 }; 2039 2040 static const enum index action_set_ipv4_dscp[] = { 2041 ACTION_SET_IPV4_DSCP_VALUE, 2042 ACTION_NEXT, 2043 ZERO, 2044 }; 2045 2046 static const enum index action_set_ipv6_dscp[] = { 2047 ACTION_SET_IPV6_DSCP_VALUE, 2048 ACTION_NEXT, 2049 ZERO, 2050 }; 2051 2052 static const enum index action_age[] = { 2053 ACTION_AGE, 2054 ACTION_AGE_TIMEOUT, 2055 ACTION_NEXT, 2056 ZERO, 2057 }; 2058 2059 static const enum index action_sample[] = { 2060 ACTION_SAMPLE, 2061 ACTION_SAMPLE_RATIO, 2062 ACTION_SAMPLE_INDEX, 2063 ACTION_NEXT, 2064 ZERO, 2065 }; 2066 2067 static const enum index next_action_sample[] = { 2068 ACTION_QUEUE, 2069 ACTION_RSS, 2070 ACTION_MARK, 2071 ACTION_COUNT, 2072 ACTION_PORT_ID, 2073 ACTION_RAW_ENCAP, 2074 ACTION_VXLAN_ENCAP, 2075 ACTION_NVGRE_ENCAP, 2076 ACTION_NEXT, 2077 ZERO, 2078 }; 2079 2080 static const enum index action_modify_field_dst[] = { 2081 ACTION_MODIFY_FIELD_DST_LEVEL, 2082 ACTION_MODIFY_FIELD_DST_OFFSET, 2083 ACTION_MODIFY_FIELD_SRC_TYPE, 2084 ZERO, 2085 }; 2086 2087 static const enum index action_modify_field_src[] = { 2088 ACTION_MODIFY_FIELD_SRC_LEVEL, 2089 ACTION_MODIFY_FIELD_SRC_OFFSET, 2090 ACTION_MODIFY_FIELD_SRC_VALUE, 2091 ACTION_MODIFY_FIELD_SRC_POINTER, 2092 ACTION_MODIFY_FIELD_WIDTH, 2093 ZERO, 2094 }; 2095 2096 static const enum index action_update_conntrack[] = { 2097 ACTION_CONNTRACK_UPDATE_DIR, 2098 ACTION_CONNTRACK_UPDATE_CTX, 2099 ACTION_NEXT, 2100 ZERO, 2101 }; 2102 2103 static const enum index action_port_representor[] = { 2104 ACTION_PORT_REPRESENTOR_PORT_ID, 2105 ACTION_NEXT, 2106 ZERO, 2107 }; 2108 2109 static const enum index action_represented_port[] = { 2110 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID, 2111 ACTION_NEXT, 2112 ZERO, 2113 }; 2114 2115 static int parse_set_raw_encap_decap(struct context *, const struct token *, 2116 const char *, unsigned int, 2117 void *, unsigned int); 2118 static int parse_set_sample_action(struct context *, const struct token *, 2119 const char *, unsigned int, 2120 void *, unsigned int); 2121 static int parse_set_init(struct context *, const struct token *, 2122 const char *, unsigned int, 2123 void *, unsigned int); 2124 static int 2125 parse_flex_handle(struct context *, const struct token *, 2126 const char *, unsigned int, void *, unsigned int); 2127 static int parse_init(struct context *, const struct token *, 2128 const char *, unsigned int, 2129 void *, unsigned int); 2130 static int parse_vc(struct context *, const struct token *, 2131 const char *, unsigned int, 2132 void *, unsigned int); 2133 static int parse_vc_spec(struct context *, const struct token *, 2134 const char *, unsigned int, void *, unsigned int); 2135 static int parse_vc_conf(struct context *, const struct token *, 2136 const char *, unsigned int, void *, unsigned int); 2137 static int parse_vc_item_ecpri_type(struct context *, const struct token *, 2138 const char *, unsigned int, 2139 void *, unsigned int); 2140 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *, 2141 const char *, unsigned int, 2142 void *, unsigned int); 2143 static int parse_vc_action_meter_color_type(struct context *, 2144 const struct token *, 2145 const char *, unsigned int, void *, 2146 unsigned int); 2147 static int parse_vc_action_rss(struct context *, const struct token *, 2148 const char *, unsigned int, void *, 2149 unsigned int); 2150 static int parse_vc_action_rss_func(struct context *, const struct token *, 2151 const char *, unsigned int, void *, 2152 unsigned int); 2153 static int parse_vc_action_rss_type(struct context *, const struct token *, 2154 const char *, unsigned int, void *, 2155 unsigned int); 2156 static int parse_vc_action_rss_queue(struct context *, const struct token *, 2157 const char *, unsigned int, void *, 2158 unsigned int); 2159 static int parse_vc_action_vxlan_encap(struct context *, const struct token *, 2160 const char *, unsigned int, void *, 2161 unsigned int); 2162 static int parse_vc_action_nvgre_encap(struct context *, const struct token *, 2163 const char *, unsigned int, void *, 2164 unsigned int); 2165 static int parse_vc_action_l2_encap(struct context *, const struct token *, 2166 const char *, unsigned int, void *, 2167 unsigned int); 2168 static int parse_vc_action_l2_decap(struct context *, const struct token *, 2169 const char *, unsigned int, void *, 2170 unsigned int); 2171 static int parse_vc_action_mplsogre_encap(struct context *, 2172 const struct token *, const char *, 2173 unsigned int, void *, unsigned int); 2174 static int parse_vc_action_mplsogre_decap(struct context *, 2175 const struct token *, const char *, 2176 unsigned int, void *, unsigned int); 2177 static int parse_vc_action_mplsoudp_encap(struct context *, 2178 const struct token *, const char *, 2179 unsigned int, void *, unsigned int); 2180 static int parse_vc_action_mplsoudp_decap(struct context *, 2181 const struct token *, const char *, 2182 unsigned int, void *, unsigned int); 2183 static int parse_vc_action_raw_encap(struct context *, 2184 const struct token *, const char *, 2185 unsigned int, void *, unsigned int); 2186 static int parse_vc_action_raw_decap(struct context *, 2187 const struct token *, const char *, 2188 unsigned int, void *, unsigned int); 2189 static int parse_vc_action_raw_encap_index(struct context *, 2190 const struct token *, const char *, 2191 unsigned int, void *, unsigned int); 2192 static int parse_vc_action_raw_decap_index(struct context *, 2193 const struct token *, const char *, 2194 unsigned int, void *, unsigned int); 2195 static int parse_vc_action_set_meta(struct context *ctx, 2196 const struct token *token, const char *str, 2197 unsigned int len, void *buf, 2198 unsigned int size); 2199 static int parse_vc_action_sample(struct context *ctx, 2200 const struct token *token, const char *str, 2201 unsigned int len, void *buf, 2202 unsigned int size); 2203 static int 2204 parse_vc_action_sample_index(struct context *ctx, const struct token *token, 2205 const char *str, unsigned int len, void *buf, 2206 unsigned int size); 2207 static int 2208 parse_vc_modify_field_op(struct context *ctx, const struct token *token, 2209 const char *str, unsigned int len, void *buf, 2210 unsigned int size); 2211 static int 2212 parse_vc_modify_field_id(struct context *ctx, const struct token *token, 2213 const char *str, unsigned int len, void *buf, 2214 unsigned int size); 2215 static int 2216 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token, 2217 const char *str, unsigned int len, void *buf, 2218 unsigned int size); 2219 static int parse_destroy(struct context *, const struct token *, 2220 const char *, unsigned int, 2221 void *, unsigned int); 2222 static int parse_flush(struct context *, const struct token *, 2223 const char *, unsigned int, 2224 void *, unsigned int); 2225 static int parse_dump(struct context *, const struct token *, 2226 const char *, unsigned int, 2227 void *, unsigned int); 2228 static int parse_query(struct context *, const struct token *, 2229 const char *, unsigned int, 2230 void *, unsigned int); 2231 static int parse_action(struct context *, const struct token *, 2232 const char *, unsigned int, 2233 void *, unsigned int); 2234 static int parse_list(struct context *, const struct token *, 2235 const char *, unsigned int, 2236 void *, unsigned int); 2237 static int parse_aged(struct context *, const struct token *, 2238 const char *, unsigned int, 2239 void *, unsigned int); 2240 static int parse_isolate(struct context *, const struct token *, 2241 const char *, unsigned int, 2242 void *, unsigned int); 2243 static int parse_configure(struct context *, const struct token *, 2244 const char *, unsigned int, 2245 void *, unsigned int); 2246 static int parse_template(struct context *, const struct token *, 2247 const char *, unsigned int, 2248 void *, unsigned int); 2249 static int parse_template_destroy(struct context *, const struct token *, 2250 const char *, unsigned int, 2251 void *, unsigned int); 2252 static int parse_table(struct context *, const struct token *, 2253 const char *, unsigned int, void *, unsigned int); 2254 static int parse_table_destroy(struct context *, const struct token *, 2255 const char *, unsigned int, 2256 void *, unsigned int); 2257 static int parse_qo(struct context *, const struct token *, 2258 const char *, unsigned int, 2259 void *, unsigned int); 2260 static int parse_qo_destroy(struct context *, const struct token *, 2261 const char *, unsigned int, 2262 void *, unsigned int); 2263 static int parse_push(struct context *, const struct token *, 2264 const char *, unsigned int, 2265 void *, unsigned int); 2266 static int parse_pull(struct context *, const struct token *, 2267 const char *, unsigned int, 2268 void *, unsigned int); 2269 static int parse_tunnel(struct context *, const struct token *, 2270 const char *, unsigned int, 2271 void *, unsigned int); 2272 static int parse_flex(struct context *, const struct token *, 2273 const char *, unsigned int, void *, unsigned int); 2274 static int parse_int(struct context *, const struct token *, 2275 const char *, unsigned int, 2276 void *, unsigned int); 2277 static int parse_prefix(struct context *, const struct token *, 2278 const char *, unsigned int, 2279 void *, unsigned int); 2280 static int parse_boolean(struct context *, const struct token *, 2281 const char *, unsigned int, 2282 void *, unsigned int); 2283 static int parse_string(struct context *, const struct token *, 2284 const char *, unsigned int, 2285 void *, unsigned int); 2286 static int parse_hex(struct context *ctx, const struct token *token, 2287 const char *str, unsigned int len, 2288 void *buf, unsigned int size); 2289 static int parse_string0(struct context *, const struct token *, 2290 const char *, unsigned int, 2291 void *, unsigned int); 2292 static int parse_mac_addr(struct context *, const struct token *, 2293 const char *, unsigned int, 2294 void *, unsigned int); 2295 static int parse_ipv4_addr(struct context *, const struct token *, 2296 const char *, unsigned int, 2297 void *, unsigned int); 2298 static int parse_ipv6_addr(struct context *, const struct token *, 2299 const char *, unsigned int, 2300 void *, unsigned int); 2301 static int parse_port(struct context *, const struct token *, 2302 const char *, unsigned int, 2303 void *, unsigned int); 2304 static int parse_ia(struct context *, const struct token *, 2305 const char *, unsigned int, 2306 void *, unsigned int); 2307 static int parse_ia_destroy(struct context *ctx, const struct token *token, 2308 const char *str, unsigned int len, 2309 void *buf, unsigned int size); 2310 static int parse_ia_id2ptr(struct context *ctx, const struct token *token, 2311 const char *str, unsigned int len, void *buf, 2312 unsigned int size); 2313 static int parse_mp(struct context *, const struct token *, 2314 const char *, unsigned int, 2315 void *, unsigned int); 2316 static int comp_none(struct context *, const struct token *, 2317 unsigned int, char *, unsigned int); 2318 static int comp_boolean(struct context *, const struct token *, 2319 unsigned int, char *, unsigned int); 2320 static int comp_action(struct context *, const struct token *, 2321 unsigned int, char *, unsigned int); 2322 static int comp_port(struct context *, const struct token *, 2323 unsigned int, char *, unsigned int); 2324 static int comp_rule_id(struct context *, const struct token *, 2325 unsigned int, char *, unsigned int); 2326 static int comp_vc_action_rss_type(struct context *, const struct token *, 2327 unsigned int, char *, unsigned int); 2328 static int comp_vc_action_rss_queue(struct context *, const struct token *, 2329 unsigned int, char *, unsigned int); 2330 static int comp_set_raw_index(struct context *, const struct token *, 2331 unsigned int, char *, unsigned int); 2332 static int comp_set_sample_index(struct context *, const struct token *, 2333 unsigned int, char *, unsigned int); 2334 static int comp_set_modify_field_op(struct context *, const struct token *, 2335 unsigned int, char *, unsigned int); 2336 static int comp_set_modify_field_id(struct context *, const struct token *, 2337 unsigned int, char *, unsigned int); 2338 static int comp_pattern_template_id(struct context *, const struct token *, 2339 unsigned int, char *, unsigned int); 2340 static int comp_actions_template_id(struct context *, const struct token *, 2341 unsigned int, char *, unsigned int); 2342 static int comp_table_id(struct context *, const struct token *, 2343 unsigned int, char *, unsigned int); 2344 static int comp_queue_id(struct context *, const struct token *, 2345 unsigned int, char *, unsigned int); 2346 2347 /** Token definitions. */ 2348 static const struct token token_list[] = { 2349 /* Special tokens. */ 2350 [ZERO] = { 2351 .name = "ZERO", 2352 .help = "null entry, abused as the entry point", 2353 .next = NEXT(NEXT_ENTRY(FLOW, ADD)), 2354 }, 2355 [END] = { 2356 .name = "", 2357 .type = "RETURN", 2358 .help = "command may end here", 2359 }, 2360 [START_SET] = { 2361 .name = "START_SET", 2362 .help = "null entry, abused as the entry point for set", 2363 .next = NEXT(NEXT_ENTRY(SET)), 2364 }, 2365 [END_SET] = { 2366 .name = "end_set", 2367 .type = "RETURN", 2368 .help = "set command may end here", 2369 }, 2370 /* Common tokens. */ 2371 [COMMON_INTEGER] = { 2372 .name = "{int}", 2373 .type = "INTEGER", 2374 .help = "integer value", 2375 .call = parse_int, 2376 .comp = comp_none, 2377 }, 2378 [COMMON_UNSIGNED] = { 2379 .name = "{unsigned}", 2380 .type = "UNSIGNED", 2381 .help = "unsigned integer value", 2382 .call = parse_int, 2383 .comp = comp_none, 2384 }, 2385 [COMMON_PREFIX] = { 2386 .name = "{prefix}", 2387 .type = "PREFIX", 2388 .help = "prefix length for bit-mask", 2389 .call = parse_prefix, 2390 .comp = comp_none, 2391 }, 2392 [COMMON_BOOLEAN] = { 2393 .name = "{boolean}", 2394 .type = "BOOLEAN", 2395 .help = "any boolean value", 2396 .call = parse_boolean, 2397 .comp = comp_boolean, 2398 }, 2399 [COMMON_STRING] = { 2400 .name = "{string}", 2401 .type = "STRING", 2402 .help = "fixed string", 2403 .call = parse_string, 2404 .comp = comp_none, 2405 }, 2406 [COMMON_HEX] = { 2407 .name = "{hex}", 2408 .type = "HEX", 2409 .help = "fixed string", 2410 .call = parse_hex, 2411 }, 2412 [COMMON_FILE_PATH] = { 2413 .name = "{file path}", 2414 .type = "STRING", 2415 .help = "file path", 2416 .call = parse_string0, 2417 .comp = comp_none, 2418 }, 2419 [COMMON_MAC_ADDR] = { 2420 .name = "{MAC address}", 2421 .type = "MAC-48", 2422 .help = "standard MAC address notation", 2423 .call = parse_mac_addr, 2424 .comp = comp_none, 2425 }, 2426 [COMMON_IPV4_ADDR] = { 2427 .name = "{IPv4 address}", 2428 .type = "IPV4 ADDRESS", 2429 .help = "standard IPv4 address notation", 2430 .call = parse_ipv4_addr, 2431 .comp = comp_none, 2432 }, 2433 [COMMON_IPV6_ADDR] = { 2434 .name = "{IPv6 address}", 2435 .type = "IPV6 ADDRESS", 2436 .help = "standard IPv6 address notation", 2437 .call = parse_ipv6_addr, 2438 .comp = comp_none, 2439 }, 2440 [COMMON_RULE_ID] = { 2441 .name = "{rule id}", 2442 .type = "RULE ID", 2443 .help = "rule identifier", 2444 .call = parse_int, 2445 .comp = comp_rule_id, 2446 }, 2447 [COMMON_PORT_ID] = { 2448 .name = "{port_id}", 2449 .type = "PORT ID", 2450 .help = "port identifier", 2451 .call = parse_port, 2452 .comp = comp_port, 2453 }, 2454 [COMMON_GROUP_ID] = { 2455 .name = "{group_id}", 2456 .type = "GROUP ID", 2457 .help = "group identifier", 2458 .call = parse_int, 2459 .comp = comp_none, 2460 }, 2461 [COMMON_PRIORITY_LEVEL] = { 2462 .name = "{level}", 2463 .type = "PRIORITY", 2464 .help = "priority level", 2465 .call = parse_int, 2466 .comp = comp_none, 2467 }, 2468 [COMMON_INDIRECT_ACTION_ID] = { 2469 .name = "{indirect_action_id}", 2470 .type = "INDIRECT_ACTION_ID", 2471 .help = "indirect action id", 2472 .call = parse_int, 2473 .comp = comp_none, 2474 }, 2475 [COMMON_POLICY_ID] = { 2476 .name = "{policy_id}", 2477 .type = "POLICY_ID", 2478 .help = "policy id", 2479 .call = parse_int, 2480 .comp = comp_none, 2481 }, 2482 [COMMON_FLEX_TOKEN] = { 2483 .name = "{flex token}", 2484 .type = "flex token", 2485 .help = "flex token", 2486 .call = parse_int, 2487 .comp = comp_none, 2488 }, 2489 [COMMON_FLEX_HANDLE] = { 2490 .name = "{flex handle}", 2491 .type = "FLEX HANDLE", 2492 .help = "fill flex item data", 2493 .call = parse_flex_handle, 2494 .comp = comp_none, 2495 }, 2496 [COMMON_PATTERN_TEMPLATE_ID] = { 2497 .name = "{pattern_template_id}", 2498 .type = "PATTERN_TEMPLATE_ID", 2499 .help = "pattern template id", 2500 .call = parse_int, 2501 .comp = comp_pattern_template_id, 2502 }, 2503 [COMMON_ACTIONS_TEMPLATE_ID] = { 2504 .name = "{actions_template_id}", 2505 .type = "ACTIONS_TEMPLATE_ID", 2506 .help = "actions template id", 2507 .call = parse_int, 2508 .comp = comp_actions_template_id, 2509 }, 2510 [COMMON_TABLE_ID] = { 2511 .name = "{table_id}", 2512 .type = "TABLE_ID", 2513 .help = "table id", 2514 .call = parse_int, 2515 .comp = comp_table_id, 2516 }, 2517 [COMMON_QUEUE_ID] = { 2518 .name = "{queue_id}", 2519 .type = "QUEUE_ID", 2520 .help = "queue id", 2521 .call = parse_int, 2522 .comp = comp_queue_id, 2523 }, 2524 /* Top-level command. */ 2525 [FLOW] = { 2526 .name = "flow", 2527 .type = "{command} {port_id} [{arg} [...]]", 2528 .help = "manage ingress/egress flow rules", 2529 .next = NEXT(NEXT_ENTRY 2530 (INFO, 2531 CONFIGURE, 2532 PATTERN_TEMPLATE, 2533 ACTIONS_TEMPLATE, 2534 TABLE, 2535 INDIRECT_ACTION, 2536 VALIDATE, 2537 CREATE, 2538 DESTROY, 2539 FLUSH, 2540 DUMP, 2541 LIST, 2542 AGED, 2543 QUERY, 2544 ISOLATE, 2545 TUNNEL, 2546 FLEX, 2547 QUEUE, 2548 PUSH, 2549 PULL)), 2550 .call = parse_init, 2551 }, 2552 /* Top-level command. */ 2553 [INFO] = { 2554 .name = "info", 2555 .help = "get information about flow engine", 2556 .next = NEXT(NEXT_ENTRY(END), 2557 NEXT_ENTRY(COMMON_PORT_ID)), 2558 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 2559 .call = parse_configure, 2560 }, 2561 /* Top-level command. */ 2562 [CONFIGURE] = { 2563 .name = "configure", 2564 .help = "configure flow engine", 2565 .next = NEXT(next_config_attr, 2566 NEXT_ENTRY(COMMON_PORT_ID)), 2567 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 2568 .call = parse_configure, 2569 }, 2570 /* Configure arguments. */ 2571 [CONFIG_QUEUES_NUMBER] = { 2572 .name = "queues_number", 2573 .help = "number of queues", 2574 .next = NEXT(next_config_attr, 2575 NEXT_ENTRY(COMMON_UNSIGNED)), 2576 .args = ARGS(ARGS_ENTRY(struct buffer, 2577 args.configure.nb_queue)), 2578 }, 2579 [CONFIG_QUEUES_SIZE] = { 2580 .name = "queues_size", 2581 .help = "number of elements in queues", 2582 .next = NEXT(next_config_attr, 2583 NEXT_ENTRY(COMMON_UNSIGNED)), 2584 .args = ARGS(ARGS_ENTRY(struct buffer, 2585 args.configure.queue_attr.size)), 2586 }, 2587 [CONFIG_COUNTERS_NUMBER] = { 2588 .name = "counters_number", 2589 .help = "number of counters", 2590 .next = NEXT(next_config_attr, 2591 NEXT_ENTRY(COMMON_UNSIGNED)), 2592 .args = ARGS(ARGS_ENTRY(struct buffer, 2593 args.configure.port_attr.nb_counters)), 2594 }, 2595 [CONFIG_AGING_OBJECTS_NUMBER] = { 2596 .name = "aging_counters_number", 2597 .help = "number of aging objects", 2598 .next = NEXT(next_config_attr, 2599 NEXT_ENTRY(COMMON_UNSIGNED)), 2600 .args = ARGS(ARGS_ENTRY(struct buffer, 2601 args.configure.port_attr.nb_aging_objects)), 2602 }, 2603 [CONFIG_METERS_NUMBER] = { 2604 .name = "meters_number", 2605 .help = "number of meters", 2606 .next = NEXT(next_config_attr, 2607 NEXT_ENTRY(COMMON_UNSIGNED)), 2608 .args = ARGS(ARGS_ENTRY(struct buffer, 2609 args.configure.port_attr.nb_meters)), 2610 }, 2611 /* Top-level command. */ 2612 [PATTERN_TEMPLATE] = { 2613 .name = "pattern_template", 2614 .type = "{command} {port_id} [{arg} [...]]", 2615 .help = "manage pattern templates", 2616 .next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), 2617 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 2618 .call = parse_template, 2619 }, 2620 /* Sub-level commands. */ 2621 [PATTERN_TEMPLATE_CREATE] = { 2622 .name = "create", 2623 .help = "create pattern template", 2624 .next = NEXT(next_pt_attr), 2625 .call = parse_template, 2626 }, 2627 [PATTERN_TEMPLATE_DESTROY] = { 2628 .name = "destroy", 2629 .help = "destroy pattern template", 2630 .next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)), 2631 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 2632 .call = parse_template_destroy, 2633 }, 2634 /* Pattern template arguments. */ 2635 [PATTERN_TEMPLATE_CREATE_ID] = { 2636 .name = "pattern_template_id", 2637 .help = "specify a pattern template id to create", 2638 .next = NEXT(next_pt_attr, 2639 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)), 2640 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)), 2641 }, 2642 [PATTERN_TEMPLATE_DESTROY_ID] = { 2643 .name = "pattern_template", 2644 .help = "specify a pattern template id to destroy", 2645 .next = NEXT(next_pt_destroy_attr, 2646 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)), 2647 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, 2648 args.templ_destroy.template_id)), 2649 .call = parse_template_destroy, 2650 }, 2651 [PATTERN_TEMPLATE_RELAXED_MATCHING] = { 2652 .name = "relaxed", 2653 .help = "is matching relaxed", 2654 .next = NEXT(next_pt_attr, 2655 NEXT_ENTRY(COMMON_BOOLEAN)), 2656 .args = ARGS(ARGS_ENTRY_BF(struct buffer, 2657 args.vc.attr.reserved, 1)), 2658 }, 2659 [PATTERN_TEMPLATE_INGRESS] = { 2660 .name = "ingress", 2661 .help = "attribute pattern to ingress", 2662 .next = NEXT(next_pt_attr), 2663 .call = parse_template, 2664 }, 2665 [PATTERN_TEMPLATE_EGRESS] = { 2666 .name = "egress", 2667 .help = "attribute pattern to egress", 2668 .next = NEXT(next_pt_attr), 2669 .call = parse_template, 2670 }, 2671 [PATTERN_TEMPLATE_TRANSFER] = { 2672 .name = "transfer", 2673 .help = "attribute pattern to transfer", 2674 .next = NEXT(next_pt_attr), 2675 .call = parse_template, 2676 }, 2677 [PATTERN_TEMPLATE_SPEC] = { 2678 .name = "template", 2679 .help = "specify item to create pattern template", 2680 .next = NEXT(next_item), 2681 }, 2682 /* Top-level command. */ 2683 [ACTIONS_TEMPLATE] = { 2684 .name = "actions_template", 2685 .type = "{command} {port_id} [{arg} [...]]", 2686 .help = "manage actions templates", 2687 .next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), 2688 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 2689 .call = parse_template, 2690 }, 2691 /* Sub-level commands. */ 2692 [ACTIONS_TEMPLATE_CREATE] = { 2693 .name = "create", 2694 .help = "create actions template", 2695 .next = NEXT(next_at_attr), 2696 .call = parse_template, 2697 }, 2698 [ACTIONS_TEMPLATE_DESTROY] = { 2699 .name = "destroy", 2700 .help = "destroy actions template", 2701 .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)), 2702 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 2703 .call = parse_template_destroy, 2704 }, 2705 /* Actions template arguments. */ 2706 [ACTIONS_TEMPLATE_CREATE_ID] = { 2707 .name = "actions_template_id", 2708 .help = "specify an actions template id to create", 2709 .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK), 2710 NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC), 2711 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)), 2712 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)), 2713 }, 2714 [ACTIONS_TEMPLATE_DESTROY_ID] = { 2715 .name = "actions_template", 2716 .help = "specify an actions template id to destroy", 2717 .next = NEXT(next_at_destroy_attr, 2718 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)), 2719 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, 2720 args.templ_destroy.template_id)), 2721 .call = parse_template_destroy, 2722 }, 2723 [ACTIONS_TEMPLATE_INGRESS] = { 2724 .name = "ingress", 2725 .help = "attribute actions to ingress", 2726 .next = NEXT(next_at_attr), 2727 .call = parse_template, 2728 }, 2729 [ACTIONS_TEMPLATE_EGRESS] = { 2730 .name = "egress", 2731 .help = "attribute actions to egress", 2732 .next = NEXT(next_at_attr), 2733 .call = parse_template, 2734 }, 2735 [ACTIONS_TEMPLATE_TRANSFER] = { 2736 .name = "transfer", 2737 .help = "attribute actions to transfer", 2738 .next = NEXT(next_at_attr), 2739 .call = parse_template, 2740 }, 2741 [ACTIONS_TEMPLATE_SPEC] = { 2742 .name = "template", 2743 .help = "specify action to create actions template", 2744 .next = NEXT(next_action), 2745 .call = parse_template, 2746 }, 2747 [ACTIONS_TEMPLATE_MASK] = { 2748 .name = "mask", 2749 .help = "specify action mask to create actions template", 2750 .next = NEXT(next_action), 2751 .call = parse_template, 2752 }, 2753 /* Top-level command. */ 2754 [TABLE] = { 2755 .name = "template_table", 2756 .type = "{command} {port_id} [{arg} [...]]", 2757 .help = "manage template tables", 2758 .next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), 2759 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 2760 .call = parse_table, 2761 }, 2762 /* Sub-level commands. */ 2763 [TABLE_CREATE] = { 2764 .name = "create", 2765 .help = "create template table", 2766 .next = NEXT(next_table_attr), 2767 .call = parse_table, 2768 }, 2769 [TABLE_DESTROY] = { 2770 .name = "destroy", 2771 .help = "destroy template table", 2772 .next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)), 2773 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 2774 .call = parse_table_destroy, 2775 }, 2776 /* Table arguments. */ 2777 [TABLE_CREATE_ID] = { 2778 .name = "table_id", 2779 .help = "specify table id to create", 2780 .next = NEXT(next_table_attr, 2781 NEXT_ENTRY(COMMON_TABLE_ID)), 2782 .args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)), 2783 }, 2784 [TABLE_DESTROY_ID] = { 2785 .name = "table", 2786 .help = "specify table id to destroy", 2787 .next = NEXT(next_table_destroy_attr, 2788 NEXT_ENTRY(COMMON_TABLE_ID)), 2789 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, 2790 args.table_destroy.table_id)), 2791 .call = parse_table_destroy, 2792 }, 2793 [TABLE_GROUP] = { 2794 .name = "group", 2795 .help = "specify a group", 2796 .next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)), 2797 .args = ARGS(ARGS_ENTRY(struct buffer, 2798 args.table.attr.flow_attr.group)), 2799 }, 2800 [TABLE_PRIORITY] = { 2801 .name = "priority", 2802 .help = "specify a priority level", 2803 .next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)), 2804 .args = ARGS(ARGS_ENTRY(struct buffer, 2805 args.table.attr.flow_attr.priority)), 2806 }, 2807 [TABLE_EGRESS] = { 2808 .name = "egress", 2809 .help = "affect rule to egress", 2810 .next = NEXT(next_table_attr), 2811 .call = parse_table, 2812 }, 2813 [TABLE_INGRESS] = { 2814 .name = "ingress", 2815 .help = "affect rule to ingress", 2816 .next = NEXT(next_table_attr), 2817 .call = parse_table, 2818 }, 2819 [TABLE_TRANSFER] = { 2820 .name = "transfer", 2821 .help = "affect rule to transfer", 2822 .next = NEXT(next_table_attr), 2823 .call = parse_table, 2824 }, 2825 [TABLE_RULES_NUMBER] = { 2826 .name = "rules_number", 2827 .help = "number of rules in table", 2828 .next = NEXT(next_table_attr, 2829 NEXT_ENTRY(COMMON_UNSIGNED)), 2830 .args = ARGS(ARGS_ENTRY(struct buffer, 2831 args.table.attr.nb_flows)), 2832 }, 2833 [TABLE_PATTERN_TEMPLATE] = { 2834 .name = "pattern_template", 2835 .help = "specify pattern template id", 2836 .next = NEXT(next_table_attr, 2837 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)), 2838 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, 2839 args.table.pat_templ_id)), 2840 .call = parse_table, 2841 }, 2842 [TABLE_ACTIONS_TEMPLATE] = { 2843 .name = "actions_template", 2844 .help = "specify actions template id", 2845 .next = NEXT(next_table_attr, 2846 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)), 2847 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, 2848 args.table.act_templ_id)), 2849 .call = parse_table, 2850 }, 2851 /* Top-level command. */ 2852 [QUEUE] = { 2853 .name = "queue", 2854 .help = "queue a flow rule operation", 2855 .next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), 2856 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 2857 .call = parse_qo, 2858 }, 2859 /* Sub-level commands. */ 2860 [QUEUE_CREATE] = { 2861 .name = "create", 2862 .help = "create a flow rule", 2863 .next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE), 2864 NEXT_ENTRY(COMMON_QUEUE_ID)), 2865 .args = ARGS(ARGS_ENTRY(struct buffer, queue)), 2866 .call = parse_qo, 2867 }, 2868 [QUEUE_DESTROY] = { 2869 .name = "destroy", 2870 .help = "destroy a flow rule", 2871 .next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID), 2872 NEXT_ENTRY(COMMON_QUEUE_ID)), 2873 .args = ARGS(ARGS_ENTRY(struct buffer, queue)), 2874 .call = parse_qo_destroy, 2875 }, 2876 /* Queue arguments. */ 2877 [QUEUE_TEMPLATE_TABLE] = { 2878 .name = "template table", 2879 .help = "specify table id", 2880 .next = NEXT(NEXT_ENTRY(QUEUE_PATTERN_TEMPLATE), 2881 NEXT_ENTRY(COMMON_TABLE_ID)), 2882 .args = ARGS(ARGS_ENTRY(struct buffer, 2883 args.vc.table_id)), 2884 .call = parse_qo, 2885 }, 2886 [QUEUE_PATTERN_TEMPLATE] = { 2887 .name = "pattern_template", 2888 .help = "specify pattern template index", 2889 .next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE), 2890 NEXT_ENTRY(COMMON_UNSIGNED)), 2891 .args = ARGS(ARGS_ENTRY(struct buffer, 2892 args.vc.pat_templ_id)), 2893 .call = parse_qo, 2894 }, 2895 [QUEUE_ACTIONS_TEMPLATE] = { 2896 .name = "actions_template", 2897 .help = "specify actions template index", 2898 .next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE), 2899 NEXT_ENTRY(COMMON_UNSIGNED)), 2900 .args = ARGS(ARGS_ENTRY(struct buffer, 2901 args.vc.act_templ_id)), 2902 .call = parse_qo, 2903 }, 2904 [QUEUE_CREATE_POSTPONE] = { 2905 .name = "postpone", 2906 .help = "postpone create operation", 2907 .next = NEXT(NEXT_ENTRY(ITEM_PATTERN), 2908 NEXT_ENTRY(COMMON_BOOLEAN)), 2909 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)), 2910 .call = parse_qo, 2911 }, 2912 [QUEUE_DESTROY_POSTPONE] = { 2913 .name = "postpone", 2914 .help = "postpone destroy operation", 2915 .next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID), 2916 NEXT_ENTRY(COMMON_BOOLEAN)), 2917 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)), 2918 .call = parse_qo_destroy, 2919 }, 2920 [QUEUE_DESTROY_ID] = { 2921 .name = "rule", 2922 .help = "specify rule id to destroy", 2923 .next = NEXT(next_queue_destroy_attr, 2924 NEXT_ENTRY(COMMON_UNSIGNED)), 2925 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, 2926 args.destroy.rule)), 2927 .call = parse_qo_destroy, 2928 }, 2929 /* Top-level command. */ 2930 [PUSH] = { 2931 .name = "push", 2932 .help = "push enqueued operations", 2933 .next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)), 2934 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 2935 .call = parse_push, 2936 }, 2937 /* Sub-level commands. */ 2938 [PUSH_QUEUE] = { 2939 .name = "queue", 2940 .help = "specify queue id", 2941 .next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)), 2942 .args = ARGS(ARGS_ENTRY(struct buffer, queue)), 2943 }, 2944 /* Top-level command. */ 2945 [PULL] = { 2946 .name = "pull", 2947 .help = "pull flow operations results", 2948 .next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)), 2949 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 2950 .call = parse_pull, 2951 }, 2952 /* Sub-level commands. */ 2953 [PULL_QUEUE] = { 2954 .name = "queue", 2955 .help = "specify queue id", 2956 .next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)), 2957 .args = ARGS(ARGS_ENTRY(struct buffer, queue)), 2958 }, 2959 /* Top-level command. */ 2960 [INDIRECT_ACTION] = { 2961 .name = "indirect_action", 2962 .type = "{command} {port_id} [{arg} [...]]", 2963 .help = "manage indirect actions", 2964 .next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), 2965 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 2966 .call = parse_ia, 2967 }, 2968 /* Sub-level commands. */ 2969 [INDIRECT_ACTION_CREATE] = { 2970 .name = "create", 2971 .help = "create indirect action", 2972 .next = NEXT(next_ia_create_attr), 2973 .call = parse_ia, 2974 }, 2975 [INDIRECT_ACTION_UPDATE] = { 2976 .name = "update", 2977 .help = "update indirect action", 2978 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC), 2979 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), 2980 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)), 2981 .call = parse_ia, 2982 }, 2983 [INDIRECT_ACTION_DESTROY] = { 2984 .name = "destroy", 2985 .help = "destroy indirect action", 2986 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)), 2987 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 2988 .call = parse_ia_destroy, 2989 }, 2990 [INDIRECT_ACTION_QUERY] = { 2991 .name = "query", 2992 .help = "query indirect action", 2993 .next = NEXT(NEXT_ENTRY(END), 2994 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), 2995 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)), 2996 .call = parse_ia, 2997 }, 2998 [VALIDATE] = { 2999 .name = "validate", 3000 .help = "check whether a flow rule can be created", 3001 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)), 3002 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3003 .call = parse_vc, 3004 }, 3005 [CREATE] = { 3006 .name = "create", 3007 .help = "create a flow rule", 3008 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)), 3009 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3010 .call = parse_vc, 3011 }, 3012 [DESTROY] = { 3013 .name = "destroy", 3014 .help = "destroy specific flow rules", 3015 .next = NEXT(NEXT_ENTRY(DESTROY_RULE), 3016 NEXT_ENTRY(COMMON_PORT_ID)), 3017 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3018 .call = parse_destroy, 3019 }, 3020 [FLUSH] = { 3021 .name = "flush", 3022 .help = "destroy all flow rules", 3023 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)), 3024 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3025 .call = parse_flush, 3026 }, 3027 [DUMP] = { 3028 .name = "dump", 3029 .help = "dump single/all flow rules to file", 3030 .next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), 3031 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3032 .call = parse_dump, 3033 }, 3034 [QUERY] = { 3035 .name = "query", 3036 .help = "query an existing flow rule", 3037 .next = NEXT(NEXT_ENTRY(QUERY_ACTION), 3038 NEXT_ENTRY(COMMON_RULE_ID), 3039 NEXT_ENTRY(COMMON_PORT_ID)), 3040 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type), 3041 ARGS_ENTRY(struct buffer, args.query.rule), 3042 ARGS_ENTRY(struct buffer, port)), 3043 .call = parse_query, 3044 }, 3045 [LIST] = { 3046 .name = "list", 3047 .help = "list existing flow rules", 3048 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)), 3049 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3050 .call = parse_list, 3051 }, 3052 [AGED] = { 3053 .name = "aged", 3054 .help = "list and destroy aged flows", 3055 .next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)), 3056 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3057 .call = parse_aged, 3058 }, 3059 [ISOLATE] = { 3060 .name = "isolate", 3061 .help = "restrict ingress traffic to the defined flow rules", 3062 .next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN), 3063 NEXT_ENTRY(COMMON_PORT_ID)), 3064 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set), 3065 ARGS_ENTRY(struct buffer, port)), 3066 .call = parse_isolate, 3067 }, 3068 [FLEX] = { 3069 .name = "flex_item", 3070 .help = "flex item API", 3071 .next = NEXT(next_flex_item), 3072 .call = parse_flex, 3073 }, 3074 [FLEX_ITEM_INIT] = { 3075 .name = "init", 3076 .help = "flex item init", 3077 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token), 3078 ARGS_ENTRY(struct buffer, port)), 3079 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN), 3080 NEXT_ENTRY(COMMON_PORT_ID)), 3081 .call = parse_flex 3082 }, 3083 [FLEX_ITEM_CREATE] = { 3084 .name = "create", 3085 .help = "flex item create", 3086 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename), 3087 ARGS_ENTRY(struct buffer, args.flex.token), 3088 ARGS_ENTRY(struct buffer, port)), 3089 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH), 3090 NEXT_ENTRY(COMMON_FLEX_TOKEN), 3091 NEXT_ENTRY(COMMON_PORT_ID)), 3092 .call = parse_flex 3093 }, 3094 [FLEX_ITEM_DESTROY] = { 3095 .name = "destroy", 3096 .help = "flex item destroy", 3097 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token), 3098 ARGS_ENTRY(struct buffer, port)), 3099 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN), 3100 NEXT_ENTRY(COMMON_PORT_ID)), 3101 .call = parse_flex 3102 }, 3103 [TUNNEL] = { 3104 .name = "tunnel", 3105 .help = "new tunnel API", 3106 .next = NEXT(NEXT_ENTRY 3107 (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)), 3108 .call = parse_tunnel, 3109 }, 3110 /* Tunnel arguments. */ 3111 [TUNNEL_CREATE] = { 3112 .name = "create", 3113 .help = "create new tunnel object", 3114 .next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE), 3115 NEXT_ENTRY(COMMON_PORT_ID)), 3116 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3117 .call = parse_tunnel, 3118 }, 3119 [TUNNEL_CREATE_TYPE] = { 3120 .name = "type", 3121 .help = "create new tunnel", 3122 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)), 3123 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)), 3124 .call = parse_tunnel, 3125 }, 3126 [TUNNEL_DESTROY] = { 3127 .name = "destroy", 3128 .help = "destroy tunnel", 3129 .next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID), 3130 NEXT_ENTRY(COMMON_PORT_ID)), 3131 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3132 .call = parse_tunnel, 3133 }, 3134 [TUNNEL_DESTROY_ID] = { 3135 .name = "id", 3136 .help = "tunnel identifier to destroy", 3137 .next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)), 3138 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)), 3139 .call = parse_tunnel, 3140 }, 3141 [TUNNEL_LIST] = { 3142 .name = "list", 3143 .help = "list existing tunnels", 3144 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)), 3145 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3146 .call = parse_tunnel, 3147 }, 3148 /* Destroy arguments. */ 3149 [DESTROY_RULE] = { 3150 .name = "rule", 3151 .help = "specify a rule identifier", 3152 .next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)), 3153 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)), 3154 .call = parse_destroy, 3155 }, 3156 /* Dump arguments. */ 3157 [DUMP_ALL] = { 3158 .name = "all", 3159 .help = "dump all", 3160 .next = NEXT(next_dump_attr), 3161 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)), 3162 .call = parse_dump, 3163 }, 3164 [DUMP_ONE] = { 3165 .name = "rule", 3166 .help = "dump one rule", 3167 .next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)), 3168 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file), 3169 ARGS_ENTRY(struct buffer, args.dump.rule)), 3170 .call = parse_dump, 3171 }, 3172 /* Query arguments. */ 3173 [QUERY_ACTION] = { 3174 .name = "{action}", 3175 .type = "ACTION", 3176 .help = "action to query, must be part of the rule", 3177 .call = parse_action, 3178 .comp = comp_action, 3179 }, 3180 /* List arguments. */ 3181 [LIST_GROUP] = { 3182 .name = "group", 3183 .help = "specify a group", 3184 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)), 3185 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)), 3186 .call = parse_list, 3187 }, 3188 [AGED_DESTROY] = { 3189 .name = "destroy", 3190 .help = "specify aged flows need be destroyed", 3191 .call = parse_aged, 3192 .comp = comp_none, 3193 }, 3194 /* Validate/create attributes. */ 3195 [VC_GROUP] = { 3196 .name = "group", 3197 .help = "specify a group", 3198 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)), 3199 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)), 3200 .call = parse_vc, 3201 }, 3202 [VC_PRIORITY] = { 3203 .name = "priority", 3204 .help = "specify a priority level", 3205 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)), 3206 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)), 3207 .call = parse_vc, 3208 }, 3209 [VC_INGRESS] = { 3210 .name = "ingress", 3211 .help = "affect rule to ingress", 3212 .next = NEXT(next_vc_attr), 3213 .call = parse_vc, 3214 }, 3215 [VC_EGRESS] = { 3216 .name = "egress", 3217 .help = "affect rule to egress", 3218 .next = NEXT(next_vc_attr), 3219 .call = parse_vc, 3220 }, 3221 [VC_TRANSFER] = { 3222 .name = "transfer", 3223 .help = "apply rule directly to endpoints found in pattern", 3224 .next = NEXT(next_vc_attr), 3225 .call = parse_vc, 3226 }, 3227 [VC_TUNNEL_SET] = { 3228 .name = "tunnel_set", 3229 .help = "tunnel steer rule", 3230 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)), 3231 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)), 3232 .call = parse_vc, 3233 }, 3234 [VC_TUNNEL_MATCH] = { 3235 .name = "tunnel_match", 3236 .help = "tunnel match rule", 3237 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)), 3238 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)), 3239 .call = parse_vc, 3240 }, 3241 /* Validate/create pattern. */ 3242 [ITEM_PATTERN] = { 3243 .name = "pattern", 3244 .help = "submit a list of pattern items", 3245 .next = NEXT(next_item), 3246 .call = parse_vc, 3247 }, 3248 [ITEM_PARAM_IS] = { 3249 .name = "is", 3250 .help = "match value perfectly (with full bit-mask)", 3251 .call = parse_vc_spec, 3252 }, 3253 [ITEM_PARAM_SPEC] = { 3254 .name = "spec", 3255 .help = "match value according to configured bit-mask", 3256 .call = parse_vc_spec, 3257 }, 3258 [ITEM_PARAM_LAST] = { 3259 .name = "last", 3260 .help = "specify upper bound to establish a range", 3261 .call = parse_vc_spec, 3262 }, 3263 [ITEM_PARAM_MASK] = { 3264 .name = "mask", 3265 .help = "specify bit-mask with relevant bits set to one", 3266 .call = parse_vc_spec, 3267 }, 3268 [ITEM_PARAM_PREFIX] = { 3269 .name = "prefix", 3270 .help = "generate bit-mask from a prefix length", 3271 .call = parse_vc_spec, 3272 }, 3273 [ITEM_NEXT] = { 3274 .name = "/", 3275 .help = "specify next pattern item", 3276 .next = NEXT(next_item), 3277 }, 3278 [ITEM_END] = { 3279 .name = "end", 3280 .help = "end list of pattern items", 3281 .priv = PRIV_ITEM(END, 0), 3282 .next = NEXT(NEXT_ENTRY(ACTIONS, END)), 3283 .call = parse_vc, 3284 }, 3285 [ITEM_VOID] = { 3286 .name = "void", 3287 .help = "no-op pattern item", 3288 .priv = PRIV_ITEM(VOID, 0), 3289 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)), 3290 .call = parse_vc, 3291 }, 3292 [ITEM_INVERT] = { 3293 .name = "invert", 3294 .help = "perform actions when pattern does not match", 3295 .priv = PRIV_ITEM(INVERT, 0), 3296 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)), 3297 .call = parse_vc, 3298 }, 3299 [ITEM_ANY] = { 3300 .name = "any", 3301 .help = "match any protocol for the current layer", 3302 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)), 3303 .next = NEXT(item_any), 3304 .call = parse_vc, 3305 }, 3306 [ITEM_ANY_NUM] = { 3307 .name = "num", 3308 .help = "number of layers covered", 3309 .next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 3310 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)), 3311 }, 3312 [ITEM_PF] = { 3313 .name = "pf", 3314 .help = "match traffic from/to the physical function", 3315 .priv = PRIV_ITEM(PF, 0), 3316 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)), 3317 .call = parse_vc, 3318 }, 3319 [ITEM_VF] = { 3320 .name = "vf", 3321 .help = "match traffic from/to a virtual function ID", 3322 .priv = PRIV_ITEM(VF, sizeof(struct rte_flow_item_vf)), 3323 .next = NEXT(item_vf), 3324 .call = parse_vc, 3325 }, 3326 [ITEM_VF_ID] = { 3327 .name = "id", 3328 .help = "VF ID", 3329 .next = NEXT(item_vf, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 3330 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_vf, id)), 3331 }, 3332 [ITEM_PHY_PORT] = { 3333 .name = "phy_port", 3334 .help = "match traffic from/to a specific physical port", 3335 .priv = PRIV_ITEM(PHY_PORT, 3336 sizeof(struct rte_flow_item_phy_port)), 3337 .next = NEXT(item_phy_port), 3338 .call = parse_vc, 3339 }, 3340 [ITEM_PHY_PORT_INDEX] = { 3341 .name = "index", 3342 .help = "physical port index", 3343 .next = NEXT(item_phy_port, NEXT_ENTRY(COMMON_UNSIGNED), 3344 item_param), 3345 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_phy_port, index)), 3346 }, 3347 [ITEM_PORT_ID] = { 3348 .name = "port_id", 3349 .help = "match traffic from/to a given DPDK port ID", 3350 .priv = PRIV_ITEM(PORT_ID, 3351 sizeof(struct rte_flow_item_port_id)), 3352 .next = NEXT(item_port_id), 3353 .call = parse_vc, 3354 }, 3355 [ITEM_PORT_ID_ID] = { 3356 .name = "id", 3357 .help = "DPDK port ID", 3358 .next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED), 3359 item_param), 3360 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)), 3361 }, 3362 [ITEM_MARK] = { 3363 .name = "mark", 3364 .help = "match traffic against value set in previously matched rule", 3365 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)), 3366 .next = NEXT(item_mark), 3367 .call = parse_vc, 3368 }, 3369 [ITEM_MARK_ID] = { 3370 .name = "id", 3371 .help = "Integer value to match against", 3372 .next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED), 3373 item_param), 3374 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)), 3375 }, 3376 [ITEM_RAW] = { 3377 .name = "raw", 3378 .help = "match an arbitrary byte string", 3379 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE), 3380 .next = NEXT(item_raw), 3381 .call = parse_vc, 3382 }, 3383 [ITEM_RAW_RELATIVE] = { 3384 .name = "relative", 3385 .help = "look for pattern after the previous item", 3386 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param), 3387 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw, 3388 relative, 1)), 3389 }, 3390 [ITEM_RAW_SEARCH] = { 3391 .name = "search", 3392 .help = "search pattern from offset (see also limit)", 3393 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param), 3394 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw, 3395 search, 1)), 3396 }, 3397 [ITEM_RAW_OFFSET] = { 3398 .name = "offset", 3399 .help = "absolute or relative offset for pattern", 3400 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param), 3401 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)), 3402 }, 3403 [ITEM_RAW_LIMIT] = { 3404 .name = "limit", 3405 .help = "search area limit for start of pattern", 3406 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 3407 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)), 3408 }, 3409 [ITEM_RAW_PATTERN] = { 3410 .name = "pattern", 3411 .help = "byte string to look for", 3412 .next = NEXT(item_raw, 3413 NEXT_ENTRY(COMMON_STRING), 3414 NEXT_ENTRY(ITEM_PARAM_IS, 3415 ITEM_PARAM_SPEC, 3416 ITEM_PARAM_MASK)), 3417 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern), 3418 ARGS_ENTRY(struct rte_flow_item_raw, length), 3419 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw), 3420 ITEM_RAW_PATTERN_SIZE)), 3421 }, 3422 [ITEM_RAW_PATTERN_HEX] = { 3423 .name = "pattern_hex", 3424 .help = "hex string to look for", 3425 .next = NEXT(item_raw, 3426 NEXT_ENTRY(COMMON_HEX), 3427 NEXT_ENTRY(ITEM_PARAM_IS, 3428 ITEM_PARAM_SPEC, 3429 ITEM_PARAM_MASK)), 3430 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern), 3431 ARGS_ENTRY(struct rte_flow_item_raw, length), 3432 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw), 3433 ITEM_RAW_PATTERN_SIZE)), 3434 }, 3435 [ITEM_ETH] = { 3436 .name = "eth", 3437 .help = "match Ethernet header", 3438 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)), 3439 .next = NEXT(item_eth), 3440 .call = parse_vc, 3441 }, 3442 [ITEM_ETH_DST] = { 3443 .name = "dst", 3444 .help = "destination MAC", 3445 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param), 3446 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, dst)), 3447 }, 3448 [ITEM_ETH_SRC] = { 3449 .name = "src", 3450 .help = "source MAC", 3451 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param), 3452 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, src)), 3453 }, 3454 [ITEM_ETH_TYPE] = { 3455 .name = "type", 3456 .help = "EtherType", 3457 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 3458 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, type)), 3459 }, 3460 [ITEM_ETH_HAS_VLAN] = { 3461 .name = "has_vlan", 3462 .help = "packet header contains VLAN", 3463 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 3464 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth, 3465 has_vlan, 1)), 3466 }, 3467 [ITEM_VLAN] = { 3468 .name = "vlan", 3469 .help = "match 802.1Q/ad VLAN tag", 3470 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)), 3471 .next = NEXT(item_vlan), 3472 .call = parse_vc, 3473 }, 3474 [ITEM_VLAN_TCI] = { 3475 .name = "tci", 3476 .help = "tag control information", 3477 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED), 3478 item_param), 3479 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, tci)), 3480 }, 3481 [ITEM_VLAN_PCP] = { 3482 .name = "pcp", 3483 .help = "priority code point", 3484 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED), 3485 item_param), 3486 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan, 3487 tci, "\xe0\x00")), 3488 }, 3489 [ITEM_VLAN_DEI] = { 3490 .name = "dei", 3491 .help = "drop eligible indicator", 3492 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED), 3493 item_param), 3494 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan, 3495 tci, "\x10\x00")), 3496 }, 3497 [ITEM_VLAN_VID] = { 3498 .name = "vid", 3499 .help = "VLAN identifier", 3500 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED), 3501 item_param), 3502 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan, 3503 tci, "\x0f\xff")), 3504 }, 3505 [ITEM_VLAN_INNER_TYPE] = { 3506 .name = "inner_type", 3507 .help = "inner EtherType", 3508 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED), 3509 item_param), 3510 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, 3511 inner_type)), 3512 }, 3513 [ITEM_VLAN_HAS_MORE_VLAN] = { 3514 .name = "has_more_vlan", 3515 .help = "packet header contains another VLAN", 3516 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED), 3517 item_param), 3518 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan, 3519 has_more_vlan, 1)), 3520 }, 3521 [ITEM_IPV4] = { 3522 .name = "ipv4", 3523 .help = "match IPv4 header", 3524 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)), 3525 .next = NEXT(item_ipv4), 3526 .call = parse_vc, 3527 }, 3528 [ITEM_IPV4_VER_IHL] = { 3529 .name = "version_ihl", 3530 .help = "match header length", 3531 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED), 3532 item_param), 3533 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4, 3534 hdr.version_ihl)), 3535 }, 3536 [ITEM_IPV4_TOS] = { 3537 .name = "tos", 3538 .help = "type of service", 3539 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED), 3540 item_param), 3541 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 3542 hdr.type_of_service)), 3543 }, 3544 [ITEM_IPV4_ID] = { 3545 .name = "packet_id", 3546 .help = "fragment packet id", 3547 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED), 3548 item_param), 3549 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 3550 hdr.packet_id)), 3551 }, 3552 [ITEM_IPV4_FRAGMENT_OFFSET] = { 3553 .name = "fragment_offset", 3554 .help = "fragmentation flags and fragment offset", 3555 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED), 3556 item_param), 3557 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 3558 hdr.fragment_offset)), 3559 }, 3560 [ITEM_IPV4_TTL] = { 3561 .name = "ttl", 3562 .help = "time to live", 3563 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED), 3564 item_param), 3565 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 3566 hdr.time_to_live)), 3567 }, 3568 [ITEM_IPV4_PROTO] = { 3569 .name = "proto", 3570 .help = "next protocol ID", 3571 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED), 3572 item_param), 3573 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 3574 hdr.next_proto_id)), 3575 }, 3576 [ITEM_IPV4_SRC] = { 3577 .name = "src", 3578 .help = "source address", 3579 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR), 3580 item_param), 3581 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 3582 hdr.src_addr)), 3583 }, 3584 [ITEM_IPV4_DST] = { 3585 .name = "dst", 3586 .help = "destination address", 3587 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR), 3588 item_param), 3589 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 3590 hdr.dst_addr)), 3591 }, 3592 [ITEM_IPV6] = { 3593 .name = "ipv6", 3594 .help = "match IPv6 header", 3595 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)), 3596 .next = NEXT(item_ipv6), 3597 .call = parse_vc, 3598 }, 3599 [ITEM_IPV6_TC] = { 3600 .name = "tc", 3601 .help = "traffic class", 3602 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED), 3603 item_param), 3604 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6, 3605 hdr.vtc_flow, 3606 "\x0f\xf0\x00\x00")), 3607 }, 3608 [ITEM_IPV6_FLOW] = { 3609 .name = "flow", 3610 .help = "flow label", 3611 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED), 3612 item_param), 3613 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6, 3614 hdr.vtc_flow, 3615 "\x00\x0f\xff\xff")), 3616 }, 3617 [ITEM_IPV6_PROTO] = { 3618 .name = "proto", 3619 .help = "protocol (next header)", 3620 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED), 3621 item_param), 3622 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 3623 hdr.proto)), 3624 }, 3625 [ITEM_IPV6_HOP] = { 3626 .name = "hop", 3627 .help = "hop limit", 3628 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED), 3629 item_param), 3630 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 3631 hdr.hop_limits)), 3632 }, 3633 [ITEM_IPV6_SRC] = { 3634 .name = "src", 3635 .help = "source address", 3636 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR), 3637 item_param), 3638 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 3639 hdr.src_addr)), 3640 }, 3641 [ITEM_IPV6_DST] = { 3642 .name = "dst", 3643 .help = "destination address", 3644 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR), 3645 item_param), 3646 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 3647 hdr.dst_addr)), 3648 }, 3649 [ITEM_IPV6_HAS_FRAG_EXT] = { 3650 .name = "has_frag_ext", 3651 .help = "fragment packet attribute", 3652 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED), 3653 item_param), 3654 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6, 3655 has_frag_ext, 1)), 3656 }, 3657 [ITEM_ICMP] = { 3658 .name = "icmp", 3659 .help = "match ICMP header", 3660 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)), 3661 .next = NEXT(item_icmp), 3662 .call = parse_vc, 3663 }, 3664 [ITEM_ICMP_TYPE] = { 3665 .name = "type", 3666 .help = "ICMP packet type", 3667 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED), 3668 item_param), 3669 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp, 3670 hdr.icmp_type)), 3671 }, 3672 [ITEM_ICMP_CODE] = { 3673 .name = "code", 3674 .help = "ICMP packet code", 3675 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED), 3676 item_param), 3677 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp, 3678 hdr.icmp_code)), 3679 }, 3680 [ITEM_ICMP_IDENT] = { 3681 .name = "ident", 3682 .help = "ICMP packet identifier", 3683 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED), 3684 item_param), 3685 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp, 3686 hdr.icmp_ident)), 3687 }, 3688 [ITEM_ICMP_SEQ] = { 3689 .name = "seq", 3690 .help = "ICMP packet sequence number", 3691 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED), 3692 item_param), 3693 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp, 3694 hdr.icmp_seq_nb)), 3695 }, 3696 [ITEM_UDP] = { 3697 .name = "udp", 3698 .help = "match UDP header", 3699 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)), 3700 .next = NEXT(item_udp), 3701 .call = parse_vc, 3702 }, 3703 [ITEM_UDP_SRC] = { 3704 .name = "src", 3705 .help = "UDP source port", 3706 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), 3707 item_param), 3708 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp, 3709 hdr.src_port)), 3710 }, 3711 [ITEM_UDP_DST] = { 3712 .name = "dst", 3713 .help = "UDP destination port", 3714 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 3715 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp, 3716 hdr.dst_port)), 3717 }, 3718 [ITEM_TCP] = { 3719 .name = "tcp", 3720 .help = "match TCP header", 3721 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)), 3722 .next = NEXT(item_tcp), 3723 .call = parse_vc, 3724 }, 3725 [ITEM_TCP_SRC] = { 3726 .name = "src", 3727 .help = "TCP source port", 3728 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 3729 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp, 3730 hdr.src_port)), 3731 }, 3732 [ITEM_TCP_DST] = { 3733 .name = "dst", 3734 .help = "TCP destination port", 3735 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 3736 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp, 3737 hdr.dst_port)), 3738 }, 3739 [ITEM_TCP_FLAGS] = { 3740 .name = "flags", 3741 .help = "TCP flags", 3742 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 3743 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp, 3744 hdr.tcp_flags)), 3745 }, 3746 [ITEM_SCTP] = { 3747 .name = "sctp", 3748 .help = "match SCTP header", 3749 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)), 3750 .next = NEXT(item_sctp), 3751 .call = parse_vc, 3752 }, 3753 [ITEM_SCTP_SRC] = { 3754 .name = "src", 3755 .help = "SCTP source port", 3756 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED), 3757 item_param), 3758 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp, 3759 hdr.src_port)), 3760 }, 3761 [ITEM_SCTP_DST] = { 3762 .name = "dst", 3763 .help = "SCTP destination port", 3764 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED), 3765 item_param), 3766 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp, 3767 hdr.dst_port)), 3768 }, 3769 [ITEM_SCTP_TAG] = { 3770 .name = "tag", 3771 .help = "validation tag", 3772 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED), 3773 item_param), 3774 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp, 3775 hdr.tag)), 3776 }, 3777 [ITEM_SCTP_CKSUM] = { 3778 .name = "cksum", 3779 .help = "checksum", 3780 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED), 3781 item_param), 3782 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp, 3783 hdr.cksum)), 3784 }, 3785 [ITEM_VXLAN] = { 3786 .name = "vxlan", 3787 .help = "match VXLAN header", 3788 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)), 3789 .next = NEXT(item_vxlan), 3790 .call = parse_vc, 3791 }, 3792 [ITEM_VXLAN_VNI] = { 3793 .name = "vni", 3794 .help = "VXLAN identifier", 3795 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED), 3796 item_param), 3797 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, vni)), 3798 }, 3799 [ITEM_VXLAN_LAST_RSVD] = { 3800 .name = "last_rsvd", 3801 .help = "VXLAN last reserved bits", 3802 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED), 3803 item_param), 3804 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, 3805 rsvd1)), 3806 }, 3807 [ITEM_E_TAG] = { 3808 .name = "e_tag", 3809 .help = "match E-Tag header", 3810 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)), 3811 .next = NEXT(item_e_tag), 3812 .call = parse_vc, 3813 }, 3814 [ITEM_E_TAG_GRP_ECID_B] = { 3815 .name = "grp_ecid_b", 3816 .help = "GRP and E-CID base", 3817 .next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED), 3818 item_param), 3819 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag, 3820 rsvd_grp_ecid_b, 3821 "\x3f\xff")), 3822 }, 3823 [ITEM_NVGRE] = { 3824 .name = "nvgre", 3825 .help = "match NVGRE header", 3826 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)), 3827 .next = NEXT(item_nvgre), 3828 .call = parse_vc, 3829 }, 3830 [ITEM_NVGRE_TNI] = { 3831 .name = "tni", 3832 .help = "virtual subnet ID", 3833 .next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED), 3834 item_param), 3835 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)), 3836 }, 3837 [ITEM_MPLS] = { 3838 .name = "mpls", 3839 .help = "match MPLS header", 3840 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)), 3841 .next = NEXT(item_mpls), 3842 .call = parse_vc, 3843 }, 3844 [ITEM_MPLS_LABEL] = { 3845 .name = "label", 3846 .help = "MPLS label", 3847 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED), 3848 item_param), 3849 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls, 3850 label_tc_s, 3851 "\xff\xff\xf0")), 3852 }, 3853 [ITEM_MPLS_TC] = { 3854 .name = "tc", 3855 .help = "MPLS Traffic Class", 3856 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED), 3857 item_param), 3858 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls, 3859 label_tc_s, 3860 "\x00\x00\x0e")), 3861 }, 3862 [ITEM_MPLS_S] = { 3863 .name = "s", 3864 .help = "MPLS Bottom-of-Stack", 3865 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED), 3866 item_param), 3867 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls, 3868 label_tc_s, 3869 "\x00\x00\x01")), 3870 }, 3871 [ITEM_GRE] = { 3872 .name = "gre", 3873 .help = "match GRE header", 3874 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)), 3875 .next = NEXT(item_gre), 3876 .call = parse_vc, 3877 }, 3878 [ITEM_GRE_PROTO] = { 3879 .name = "protocol", 3880 .help = "GRE protocol type", 3881 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED), 3882 item_param), 3883 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre, 3884 protocol)), 3885 }, 3886 [ITEM_GRE_C_RSVD0_VER] = { 3887 .name = "c_rsvd0_ver", 3888 .help = 3889 "checksum (1b), undefined (1b), key bit (1b)," 3890 " sequence number (1b), reserved 0 (9b)," 3891 " version (3b)", 3892 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED), 3893 item_param), 3894 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre, 3895 c_rsvd0_ver)), 3896 }, 3897 [ITEM_GRE_C_BIT] = { 3898 .name = "c_bit", 3899 .help = "checksum bit (C)", 3900 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), 3901 item_param), 3902 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre, 3903 c_rsvd0_ver, 3904 "\x80\x00\x00\x00")), 3905 }, 3906 [ITEM_GRE_S_BIT] = { 3907 .name = "s_bit", 3908 .help = "sequence number bit (S)", 3909 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param), 3910 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre, 3911 c_rsvd0_ver, 3912 "\x10\x00\x00\x00")), 3913 }, 3914 [ITEM_GRE_K_BIT] = { 3915 .name = "k_bit", 3916 .help = "key bit (K)", 3917 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param), 3918 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre, 3919 c_rsvd0_ver, 3920 "\x20\x00\x00\x00")), 3921 }, 3922 [ITEM_FUZZY] = { 3923 .name = "fuzzy", 3924 .help = "fuzzy pattern match, expect faster than default", 3925 .priv = PRIV_ITEM(FUZZY, 3926 sizeof(struct rte_flow_item_fuzzy)), 3927 .next = NEXT(item_fuzzy), 3928 .call = parse_vc, 3929 }, 3930 [ITEM_FUZZY_THRESH] = { 3931 .name = "thresh", 3932 .help = "match accuracy threshold", 3933 .next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED), 3934 item_param), 3935 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy, 3936 thresh)), 3937 }, 3938 [ITEM_GTP] = { 3939 .name = "gtp", 3940 .help = "match GTP header", 3941 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)), 3942 .next = NEXT(item_gtp), 3943 .call = parse_vc, 3944 }, 3945 [ITEM_GTP_FLAGS] = { 3946 .name = "v_pt_rsv_flags", 3947 .help = "GTP flags", 3948 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 3949 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, 3950 v_pt_rsv_flags)), 3951 }, 3952 [ITEM_GTP_MSG_TYPE] = { 3953 .name = "msg_type", 3954 .help = "GTP message type", 3955 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 3956 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)), 3957 }, 3958 [ITEM_GTP_TEID] = { 3959 .name = "teid", 3960 .help = "tunnel endpoint identifier", 3961 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 3962 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)), 3963 }, 3964 [ITEM_GTPC] = { 3965 .name = "gtpc", 3966 .help = "match GTP header", 3967 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)), 3968 .next = NEXT(item_gtp), 3969 .call = parse_vc, 3970 }, 3971 [ITEM_GTPU] = { 3972 .name = "gtpu", 3973 .help = "match GTP header", 3974 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)), 3975 .next = NEXT(item_gtp), 3976 .call = parse_vc, 3977 }, 3978 [ITEM_GENEVE] = { 3979 .name = "geneve", 3980 .help = "match GENEVE header", 3981 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)), 3982 .next = NEXT(item_geneve), 3983 .call = parse_vc, 3984 }, 3985 [ITEM_GENEVE_VNI] = { 3986 .name = "vni", 3987 .help = "virtual network identifier", 3988 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED), 3989 item_param), 3990 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)), 3991 }, 3992 [ITEM_GENEVE_PROTO] = { 3993 .name = "protocol", 3994 .help = "GENEVE protocol type", 3995 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED), 3996 item_param), 3997 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, 3998 protocol)), 3999 }, 4000 [ITEM_GENEVE_OPTLEN] = { 4001 .name = "optlen", 4002 .help = "GENEVE options length in dwords", 4003 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED), 4004 item_param), 4005 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve, 4006 ver_opt_len_o_c_rsvd0, 4007 "\x3f\x00")), 4008 }, 4009 [ITEM_VXLAN_GPE] = { 4010 .name = "vxlan-gpe", 4011 .help = "match VXLAN-GPE header", 4012 .priv = PRIV_ITEM(VXLAN_GPE, 4013 sizeof(struct rte_flow_item_vxlan_gpe)), 4014 .next = NEXT(item_vxlan_gpe), 4015 .call = parse_vc, 4016 }, 4017 [ITEM_VXLAN_GPE_VNI] = { 4018 .name = "vni", 4019 .help = "VXLAN-GPE identifier", 4020 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED), 4021 item_param), 4022 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe, 4023 vni)), 4024 }, 4025 [ITEM_ARP_ETH_IPV4] = { 4026 .name = "arp_eth_ipv4", 4027 .help = "match ARP header for Ethernet/IPv4", 4028 .priv = PRIV_ITEM(ARP_ETH_IPV4, 4029 sizeof(struct rte_flow_item_arp_eth_ipv4)), 4030 .next = NEXT(item_arp_eth_ipv4), 4031 .call = parse_vc, 4032 }, 4033 [ITEM_ARP_ETH_IPV4_SHA] = { 4034 .name = "sha", 4035 .help = "sender hardware address", 4036 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR), 4037 item_param), 4038 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4, 4039 sha)), 4040 }, 4041 [ITEM_ARP_ETH_IPV4_SPA] = { 4042 .name = "spa", 4043 .help = "sender IPv4 address", 4044 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR), 4045 item_param), 4046 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4, 4047 spa)), 4048 }, 4049 [ITEM_ARP_ETH_IPV4_THA] = { 4050 .name = "tha", 4051 .help = "target hardware address", 4052 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR), 4053 item_param), 4054 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4, 4055 tha)), 4056 }, 4057 [ITEM_ARP_ETH_IPV4_TPA] = { 4058 .name = "tpa", 4059 .help = "target IPv4 address", 4060 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR), 4061 item_param), 4062 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4, 4063 tpa)), 4064 }, 4065 [ITEM_IPV6_EXT] = { 4066 .name = "ipv6_ext", 4067 .help = "match presence of any IPv6 extension header", 4068 .priv = PRIV_ITEM(IPV6_EXT, 4069 sizeof(struct rte_flow_item_ipv6_ext)), 4070 .next = NEXT(item_ipv6_ext), 4071 .call = parse_vc, 4072 }, 4073 [ITEM_IPV6_EXT_NEXT_HDR] = { 4074 .name = "next_hdr", 4075 .help = "next header", 4076 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED), 4077 item_param), 4078 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext, 4079 next_hdr)), 4080 }, 4081 [ITEM_IPV6_FRAG_EXT] = { 4082 .name = "ipv6_frag_ext", 4083 .help = "match presence of IPv6 fragment extension header", 4084 .priv = PRIV_ITEM(IPV6_FRAG_EXT, 4085 sizeof(struct rte_flow_item_ipv6_frag_ext)), 4086 .next = NEXT(item_ipv6_frag_ext), 4087 .call = parse_vc, 4088 }, 4089 [ITEM_IPV6_FRAG_EXT_NEXT_HDR] = { 4090 .name = "next_hdr", 4091 .help = "next header", 4092 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED), 4093 item_param), 4094 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext, 4095 hdr.next_header)), 4096 }, 4097 [ITEM_IPV6_FRAG_EXT_FRAG_DATA] = { 4098 .name = "frag_data", 4099 .help = "fragment flags and offset", 4100 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED), 4101 item_param), 4102 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext, 4103 hdr.frag_data)), 4104 }, 4105 [ITEM_IPV6_FRAG_EXT_ID] = { 4106 .name = "packet_id", 4107 .help = "fragment packet id", 4108 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED), 4109 item_param), 4110 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext, 4111 hdr.id)), 4112 }, 4113 [ITEM_ICMP6] = { 4114 .name = "icmp6", 4115 .help = "match any ICMPv6 header", 4116 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)), 4117 .next = NEXT(item_icmp6), 4118 .call = parse_vc, 4119 }, 4120 [ITEM_ICMP6_TYPE] = { 4121 .name = "type", 4122 .help = "ICMPv6 type", 4123 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED), 4124 item_param), 4125 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6, 4126 type)), 4127 }, 4128 [ITEM_ICMP6_CODE] = { 4129 .name = "code", 4130 .help = "ICMPv6 code", 4131 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED), 4132 item_param), 4133 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6, 4134 code)), 4135 }, 4136 [ITEM_ICMP6_ND_NS] = { 4137 .name = "icmp6_nd_ns", 4138 .help = "match ICMPv6 neighbor discovery solicitation", 4139 .priv = PRIV_ITEM(ICMP6_ND_NS, 4140 sizeof(struct rte_flow_item_icmp6_nd_ns)), 4141 .next = NEXT(item_icmp6_nd_ns), 4142 .call = parse_vc, 4143 }, 4144 [ITEM_ICMP6_ND_NS_TARGET_ADDR] = { 4145 .name = "target_addr", 4146 .help = "target address", 4147 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR), 4148 item_param), 4149 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns, 4150 target_addr)), 4151 }, 4152 [ITEM_ICMP6_ND_NA] = { 4153 .name = "icmp6_nd_na", 4154 .help = "match ICMPv6 neighbor discovery advertisement", 4155 .priv = PRIV_ITEM(ICMP6_ND_NA, 4156 sizeof(struct rte_flow_item_icmp6_nd_na)), 4157 .next = NEXT(item_icmp6_nd_na), 4158 .call = parse_vc, 4159 }, 4160 [ITEM_ICMP6_ND_NA_TARGET_ADDR] = { 4161 .name = "target_addr", 4162 .help = "target address", 4163 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR), 4164 item_param), 4165 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na, 4166 target_addr)), 4167 }, 4168 [ITEM_ICMP6_ND_OPT] = { 4169 .name = "icmp6_nd_opt", 4170 .help = "match presence of any ICMPv6 neighbor discovery" 4171 " option", 4172 .priv = PRIV_ITEM(ICMP6_ND_OPT, 4173 sizeof(struct rte_flow_item_icmp6_nd_opt)), 4174 .next = NEXT(item_icmp6_nd_opt), 4175 .call = parse_vc, 4176 }, 4177 [ITEM_ICMP6_ND_OPT_TYPE] = { 4178 .name = "type", 4179 .help = "ND option type", 4180 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED), 4181 item_param), 4182 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt, 4183 type)), 4184 }, 4185 [ITEM_ICMP6_ND_OPT_SLA_ETH] = { 4186 .name = "icmp6_nd_opt_sla_eth", 4187 .help = "match ICMPv6 neighbor discovery source Ethernet" 4188 " link-layer address option", 4189 .priv = PRIV_ITEM 4190 (ICMP6_ND_OPT_SLA_ETH, 4191 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)), 4192 .next = NEXT(item_icmp6_nd_opt_sla_eth), 4193 .call = parse_vc, 4194 }, 4195 [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = { 4196 .name = "sla", 4197 .help = "source Ethernet LLA", 4198 .next = NEXT(item_icmp6_nd_opt_sla_eth, 4199 NEXT_ENTRY(COMMON_MAC_ADDR), item_param), 4200 .args = ARGS(ARGS_ENTRY_HTON 4201 (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)), 4202 }, 4203 [ITEM_ICMP6_ND_OPT_TLA_ETH] = { 4204 .name = "icmp6_nd_opt_tla_eth", 4205 .help = "match ICMPv6 neighbor discovery target Ethernet" 4206 " link-layer address option", 4207 .priv = PRIV_ITEM 4208 (ICMP6_ND_OPT_TLA_ETH, 4209 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)), 4210 .next = NEXT(item_icmp6_nd_opt_tla_eth), 4211 .call = parse_vc, 4212 }, 4213 [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = { 4214 .name = "tla", 4215 .help = "target Ethernet LLA", 4216 .next = NEXT(item_icmp6_nd_opt_tla_eth, 4217 NEXT_ENTRY(COMMON_MAC_ADDR), item_param), 4218 .args = ARGS(ARGS_ENTRY_HTON 4219 (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)), 4220 }, 4221 [ITEM_META] = { 4222 .name = "meta", 4223 .help = "match metadata header", 4224 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)), 4225 .next = NEXT(item_meta), 4226 .call = parse_vc, 4227 }, 4228 [ITEM_META_DATA] = { 4229 .name = "data", 4230 .help = "metadata value", 4231 .next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED), 4232 item_param), 4233 .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta, 4234 data, "\xff\xff\xff\xff")), 4235 }, 4236 [ITEM_GRE_KEY] = { 4237 .name = "gre_key", 4238 .help = "match GRE key", 4239 .priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)), 4240 .next = NEXT(item_gre_key), 4241 .call = parse_vc, 4242 }, 4243 [ITEM_GRE_KEY_VALUE] = { 4244 .name = "value", 4245 .help = "key value", 4246 .next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED), 4247 item_param), 4248 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)), 4249 }, 4250 [ITEM_GRE_OPTION] = { 4251 .name = "gre_option", 4252 .help = "match GRE optional fields", 4253 .priv = PRIV_ITEM(GRE_OPTION, 4254 sizeof(struct rte_flow_item_gre_opt)), 4255 .next = NEXT(item_gre_option), 4256 .call = parse_vc, 4257 }, 4258 [ITEM_GRE_OPTION_CHECKSUM] = { 4259 .name = "checksum", 4260 .help = "match GRE checksum", 4261 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED), 4262 item_param), 4263 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt, 4264 checksum_rsvd.checksum)), 4265 }, 4266 [ITEM_GRE_OPTION_KEY] = { 4267 .name = "key", 4268 .help = "match GRE key", 4269 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED), 4270 item_param), 4271 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt, 4272 key.key)), 4273 }, 4274 [ITEM_GRE_OPTION_SEQUENCE] = { 4275 .name = "sequence", 4276 .help = "match GRE sequence", 4277 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED), 4278 item_param), 4279 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt, 4280 sequence.sequence)), 4281 }, 4282 [ITEM_GTP_PSC] = { 4283 .name = "gtp_psc", 4284 .help = "match GTP extension header with type 0x85", 4285 .priv = PRIV_ITEM(GTP_PSC, 4286 sizeof(struct rte_flow_item_gtp_psc)), 4287 .next = NEXT(item_gtp_psc), 4288 .call = parse_vc, 4289 }, 4290 [ITEM_GTP_PSC_QFI] = { 4291 .name = "qfi", 4292 .help = "QoS flow identifier", 4293 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED), 4294 item_param), 4295 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc, 4296 hdr.qfi, 6)), 4297 }, 4298 [ITEM_GTP_PSC_PDU_T] = { 4299 .name = "pdu_t", 4300 .help = "PDU type", 4301 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED), 4302 item_param), 4303 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc, 4304 hdr.type, 4)), 4305 }, 4306 [ITEM_PPPOES] = { 4307 .name = "pppoes", 4308 .help = "match PPPoE session header", 4309 .priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)), 4310 .next = NEXT(item_pppoes), 4311 .call = parse_vc, 4312 }, 4313 [ITEM_PPPOED] = { 4314 .name = "pppoed", 4315 .help = "match PPPoE discovery header", 4316 .priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)), 4317 .next = NEXT(item_pppoed), 4318 .call = parse_vc, 4319 }, 4320 [ITEM_PPPOE_SEID] = { 4321 .name = "seid", 4322 .help = "session identifier", 4323 .next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED), 4324 item_param), 4325 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe, 4326 session_id)), 4327 }, 4328 [ITEM_PPPOE_PROTO_ID] = { 4329 .name = "pppoe_proto_id", 4330 .help = "match PPPoE session protocol identifier", 4331 .priv = PRIV_ITEM(PPPOE_PROTO_ID, 4332 sizeof(struct rte_flow_item_pppoe_proto_id)), 4333 .next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED), 4334 item_param), 4335 .args = ARGS(ARGS_ENTRY_HTON 4336 (struct rte_flow_item_pppoe_proto_id, proto_id)), 4337 .call = parse_vc, 4338 }, 4339 [ITEM_HIGIG2] = { 4340 .name = "higig2", 4341 .help = "matches higig2 header", 4342 .priv = PRIV_ITEM(HIGIG2, 4343 sizeof(struct rte_flow_item_higig2_hdr)), 4344 .next = NEXT(item_higig2), 4345 .call = parse_vc, 4346 }, 4347 [ITEM_HIGIG2_CLASSIFICATION] = { 4348 .name = "classification", 4349 .help = "matches classification of higig2 header", 4350 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED), 4351 item_param), 4352 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr, 4353 hdr.ppt1.classification)), 4354 }, 4355 [ITEM_HIGIG2_VID] = { 4356 .name = "vid", 4357 .help = "matches vid of higig2 header", 4358 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED), 4359 item_param), 4360 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr, 4361 hdr.ppt1.vid)), 4362 }, 4363 [ITEM_TAG] = { 4364 .name = "tag", 4365 .help = "match tag value", 4366 .priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)), 4367 .next = NEXT(item_tag), 4368 .call = parse_vc, 4369 }, 4370 [ITEM_TAG_DATA] = { 4371 .name = "data", 4372 .help = "tag value to match", 4373 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 4374 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)), 4375 }, 4376 [ITEM_TAG_INDEX] = { 4377 .name = "index", 4378 .help = "index of tag array to match", 4379 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), 4380 NEXT_ENTRY(ITEM_PARAM_IS)), 4381 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)), 4382 }, 4383 [ITEM_L2TPV3OIP] = { 4384 .name = "l2tpv3oip", 4385 .help = "match L2TPv3 over IP header", 4386 .priv = PRIV_ITEM(L2TPV3OIP, 4387 sizeof(struct rte_flow_item_l2tpv3oip)), 4388 .next = NEXT(item_l2tpv3oip), 4389 .call = parse_vc, 4390 }, 4391 [ITEM_L2TPV3OIP_SESSION_ID] = { 4392 .name = "session_id", 4393 .help = "session identifier", 4394 .next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED), 4395 item_param), 4396 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip, 4397 session_id)), 4398 }, 4399 [ITEM_ESP] = { 4400 .name = "esp", 4401 .help = "match ESP header", 4402 .priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)), 4403 .next = NEXT(item_esp), 4404 .call = parse_vc, 4405 }, 4406 [ITEM_ESP_SPI] = { 4407 .name = "spi", 4408 .help = "security policy index", 4409 .next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 4410 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp, 4411 hdr.spi)), 4412 }, 4413 [ITEM_AH] = { 4414 .name = "ah", 4415 .help = "match AH header", 4416 .priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)), 4417 .next = NEXT(item_ah), 4418 .call = parse_vc, 4419 }, 4420 [ITEM_AH_SPI] = { 4421 .name = "spi", 4422 .help = "security parameters index", 4423 .next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 4424 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)), 4425 }, 4426 [ITEM_PFCP] = { 4427 .name = "pfcp", 4428 .help = "match pfcp header", 4429 .priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)), 4430 .next = NEXT(item_pfcp), 4431 .call = parse_vc, 4432 }, 4433 [ITEM_PFCP_S_FIELD] = { 4434 .name = "s_field", 4435 .help = "S field", 4436 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED), 4437 item_param), 4438 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, 4439 s_field)), 4440 }, 4441 [ITEM_PFCP_SEID] = { 4442 .name = "seid", 4443 .help = "session endpoint identifier", 4444 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED), 4445 item_param), 4446 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)), 4447 }, 4448 [ITEM_ECPRI] = { 4449 .name = "ecpri", 4450 .help = "match eCPRI header", 4451 .priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)), 4452 .next = NEXT(item_ecpri), 4453 .call = parse_vc, 4454 }, 4455 [ITEM_ECPRI_COMMON] = { 4456 .name = "common", 4457 .help = "eCPRI common header", 4458 .next = NEXT(item_ecpri_common), 4459 }, 4460 [ITEM_ECPRI_COMMON_TYPE] = { 4461 .name = "type", 4462 .help = "type of common header", 4463 .next = NEXT(item_ecpri_common_type), 4464 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)), 4465 }, 4466 [ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = { 4467 .name = "iq_data", 4468 .help = "Type #0: IQ Data", 4469 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID, 4470 ITEM_NEXT)), 4471 .call = parse_vc_item_ecpri_type, 4472 }, 4473 [ITEM_ECPRI_MSG_IQ_DATA_PCID] = { 4474 .name = "pc_id", 4475 .help = "Physical Channel ID", 4476 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID, 4477 ITEM_ECPRI_COMMON, ITEM_NEXT), 4478 NEXT_ENTRY(COMMON_UNSIGNED), item_param), 4479 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri, 4480 hdr.type0.pc_id)), 4481 }, 4482 [ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = { 4483 .name = "rtc_ctrl", 4484 .help = "Type #2: Real-Time Control Data", 4485 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID, 4486 ITEM_NEXT)), 4487 .call = parse_vc_item_ecpri_type, 4488 }, 4489 [ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = { 4490 .name = "rtc_id", 4491 .help = "Real-Time Control Data ID", 4492 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID, 4493 ITEM_ECPRI_COMMON, ITEM_NEXT), 4494 NEXT_ENTRY(COMMON_UNSIGNED), item_param), 4495 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri, 4496 hdr.type2.rtc_id)), 4497 }, 4498 [ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = { 4499 .name = "delay_measure", 4500 .help = "Type #5: One-Way Delay Measurement", 4501 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID, 4502 ITEM_NEXT)), 4503 .call = parse_vc_item_ecpri_type, 4504 }, 4505 [ITEM_ECPRI_MSG_DLY_MSR_MSRID] = { 4506 .name = "msr_id", 4507 .help = "Measurement ID", 4508 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID, 4509 ITEM_ECPRI_COMMON, ITEM_NEXT), 4510 NEXT_ENTRY(COMMON_UNSIGNED), item_param), 4511 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri, 4512 hdr.type5.msr_id)), 4513 }, 4514 [ITEM_GENEVE_OPT] = { 4515 .name = "geneve-opt", 4516 .help = "GENEVE header option", 4517 .priv = PRIV_ITEM(GENEVE_OPT, 4518 sizeof(struct rte_flow_item_geneve_opt) + 4519 ITEM_GENEVE_OPT_DATA_SIZE), 4520 .next = NEXT(item_geneve_opt), 4521 .call = parse_vc, 4522 }, 4523 [ITEM_GENEVE_OPT_CLASS] = { 4524 .name = "class", 4525 .help = "GENEVE option class", 4526 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED), 4527 item_param), 4528 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt, 4529 option_class)), 4530 }, 4531 [ITEM_GENEVE_OPT_TYPE] = { 4532 .name = "type", 4533 .help = "GENEVE option type", 4534 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED), 4535 item_param), 4536 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, 4537 option_type)), 4538 }, 4539 [ITEM_GENEVE_OPT_LENGTH] = { 4540 .name = "length", 4541 .help = "GENEVE option data length (in 32b words)", 4542 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED), 4543 item_param), 4544 .args = ARGS(ARGS_ENTRY_BOUNDED( 4545 struct rte_flow_item_geneve_opt, option_len, 4546 0, 31)), 4547 }, 4548 [ITEM_GENEVE_OPT_DATA] = { 4549 .name = "data", 4550 .help = "GENEVE option data pattern", 4551 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX), 4552 item_param), 4553 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data), 4554 ARGS_ENTRY_ARB(0, 0), 4555 ARGS_ENTRY_ARB 4556 (sizeof(struct rte_flow_item_geneve_opt), 4557 ITEM_GENEVE_OPT_DATA_SIZE)), 4558 }, 4559 [ITEM_INTEGRITY] = { 4560 .name = "integrity", 4561 .help = "match packet integrity", 4562 .priv = PRIV_ITEM(INTEGRITY, 4563 sizeof(struct rte_flow_item_integrity)), 4564 .next = NEXT(item_integrity), 4565 .call = parse_vc, 4566 }, 4567 [ITEM_INTEGRITY_LEVEL] = { 4568 .name = "level", 4569 .help = "integrity level", 4570 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED), 4571 item_param), 4572 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)), 4573 }, 4574 [ITEM_INTEGRITY_VALUE] = { 4575 .name = "value", 4576 .help = "integrity value", 4577 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED), 4578 item_param), 4579 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)), 4580 }, 4581 [ITEM_CONNTRACK] = { 4582 .name = "conntrack", 4583 .help = "conntrack state", 4584 .next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED), 4585 item_param), 4586 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)), 4587 }, 4588 [ITEM_PORT_REPRESENTOR] = { 4589 .name = "port_representor", 4590 .help = "match traffic entering the embedded switch from the given ethdev", 4591 .priv = PRIV_ITEM(PORT_REPRESENTOR, 4592 sizeof(struct rte_flow_item_ethdev)), 4593 .next = NEXT(item_port_representor), 4594 .call = parse_vc, 4595 }, 4596 [ITEM_PORT_REPRESENTOR_PORT_ID] = { 4597 .name = "port_id", 4598 .help = "ethdev port ID", 4599 .next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED), 4600 item_param), 4601 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)), 4602 }, 4603 [ITEM_REPRESENTED_PORT] = { 4604 .name = "represented_port", 4605 .help = "match traffic entering the embedded switch from the entity represented by the given ethdev", 4606 .priv = PRIV_ITEM(REPRESENTED_PORT, 4607 sizeof(struct rte_flow_item_ethdev)), 4608 .next = NEXT(item_represented_port), 4609 .call = parse_vc, 4610 }, 4611 [ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = { 4612 .name = "ethdev_port_id", 4613 .help = "ethdev port ID", 4614 .next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED), 4615 item_param), 4616 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)), 4617 }, 4618 [ITEM_FLEX] = { 4619 .name = "flex", 4620 .help = "match flex header", 4621 .priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)), 4622 .next = NEXT(item_flex), 4623 .call = parse_vc, 4624 }, 4625 [ITEM_FLEX_ITEM_HANDLE] = { 4626 .name = "item", 4627 .help = "flex item handle", 4628 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE), 4629 NEXT_ENTRY(ITEM_PARAM_IS)), 4630 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)), 4631 }, 4632 [ITEM_FLEX_PATTERN_HANDLE] = { 4633 .name = "pattern", 4634 .help = "flex pattern handle", 4635 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE), 4636 NEXT_ENTRY(ITEM_PARAM_IS)), 4637 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)), 4638 }, 4639 [ITEM_L2TPV2] = { 4640 .name = "l2tpv2", 4641 .help = "match L2TPv2 header", 4642 .priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)), 4643 .next = NEXT(item_l2tpv2), 4644 .call = parse_vc, 4645 }, 4646 [ITEM_L2TPV2_TYPE] = { 4647 .name = "type", 4648 .help = "type of l2tpv2", 4649 .next = NEXT(item_l2tpv2_type), 4650 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)), 4651 }, 4652 [ITEM_L2TPV2_TYPE_DATA] = { 4653 .name = "data", 4654 .help = "Type #7: data message without any options", 4655 .next = NEXT(item_l2tpv2_type_data), 4656 .call = parse_vc_item_l2tpv2_type, 4657 }, 4658 [ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = { 4659 .name = "tunnel_id", 4660 .help = "tunnel identifier", 4661 .next = NEXT(item_l2tpv2_type_data, 4662 NEXT_ENTRY(COMMON_UNSIGNED), 4663 item_param), 4664 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4665 hdr.type7.tunnel_id)), 4666 }, 4667 [ITEM_L2TPV2_MSG_DATA_SESSION_ID] = { 4668 .name = "session_id", 4669 .help = "session identifier", 4670 .next = NEXT(item_l2tpv2_type_data, 4671 NEXT_ENTRY(COMMON_UNSIGNED), 4672 item_param), 4673 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4674 hdr.type7.session_id)), 4675 }, 4676 [ITEM_L2TPV2_TYPE_DATA_L] = { 4677 .name = "data_l", 4678 .help = "Type #6: data message with length option", 4679 .next = NEXT(item_l2tpv2_type_data_l), 4680 .call = parse_vc_item_l2tpv2_type, 4681 }, 4682 [ITEM_L2TPV2_MSG_DATA_L_LENGTH] = { 4683 .name = "length", 4684 .help = "message length", 4685 .next = NEXT(item_l2tpv2_type_data_l, 4686 NEXT_ENTRY(COMMON_UNSIGNED), 4687 item_param), 4688 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4689 hdr.type6.length)), 4690 }, 4691 [ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = { 4692 .name = "tunnel_id", 4693 .help = "tunnel identifier", 4694 .next = NEXT(item_l2tpv2_type_data_l, 4695 NEXT_ENTRY(COMMON_UNSIGNED), 4696 item_param), 4697 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4698 hdr.type6.tunnel_id)), 4699 }, 4700 [ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = { 4701 .name = "session_id", 4702 .help = "session identifier", 4703 .next = NEXT(item_l2tpv2_type_data_l, 4704 NEXT_ENTRY(COMMON_UNSIGNED), 4705 item_param), 4706 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4707 hdr.type6.session_id)), 4708 }, 4709 [ITEM_L2TPV2_TYPE_DATA_S] = { 4710 .name = "data_s", 4711 .help = "Type #5: data message with ns, nr option", 4712 .next = NEXT(item_l2tpv2_type_data_s), 4713 .call = parse_vc_item_l2tpv2_type, 4714 }, 4715 [ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = { 4716 .name = "tunnel_id", 4717 .help = "tunnel identifier", 4718 .next = NEXT(item_l2tpv2_type_data_s, 4719 NEXT_ENTRY(COMMON_UNSIGNED), 4720 item_param), 4721 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4722 hdr.type5.tunnel_id)), 4723 }, 4724 [ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = { 4725 .name = "session_id", 4726 .help = "session identifier", 4727 .next = NEXT(item_l2tpv2_type_data_s, 4728 NEXT_ENTRY(COMMON_UNSIGNED), 4729 item_param), 4730 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4731 hdr.type5.session_id)), 4732 }, 4733 [ITEM_L2TPV2_MSG_DATA_S_NS] = { 4734 .name = "ns", 4735 .help = "sequence number for message", 4736 .next = NEXT(item_l2tpv2_type_data_s, 4737 NEXT_ENTRY(COMMON_UNSIGNED), 4738 item_param), 4739 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4740 hdr.type5.ns)), 4741 }, 4742 [ITEM_L2TPV2_MSG_DATA_S_NR] = { 4743 .name = "nr", 4744 .help = "sequence number for next receive message", 4745 .next = NEXT(item_l2tpv2_type_data_s, 4746 NEXT_ENTRY(COMMON_UNSIGNED), 4747 item_param), 4748 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4749 hdr.type5.nr)), 4750 }, 4751 [ITEM_L2TPV2_TYPE_DATA_O] = { 4752 .name = "data_o", 4753 .help = "Type #4: data message with offset option", 4754 .next = NEXT(item_l2tpv2_type_data_o), 4755 .call = parse_vc_item_l2tpv2_type, 4756 }, 4757 [ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = { 4758 .name = "tunnel_id", 4759 .help = "tunnel identifier", 4760 .next = NEXT(item_l2tpv2_type_data_o, 4761 NEXT_ENTRY(COMMON_UNSIGNED), 4762 item_param), 4763 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4764 hdr.type4.tunnel_id)), 4765 }, 4766 [ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = { 4767 .name = "session_id", 4768 .help = "session identifier", 4769 .next = NEXT(item_l2tpv2_type_data_o, 4770 NEXT_ENTRY(COMMON_UNSIGNED), 4771 item_param), 4772 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4773 hdr.type5.session_id)), 4774 }, 4775 [ITEM_L2TPV2_MSG_DATA_O_OFFSET] = { 4776 .name = "offset_size", 4777 .help = "the size of offset padding", 4778 .next = NEXT(item_l2tpv2_type_data_o, 4779 NEXT_ENTRY(COMMON_UNSIGNED), 4780 item_param), 4781 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4782 hdr.type4.offset_size)), 4783 }, 4784 [ITEM_L2TPV2_TYPE_DATA_L_S] = { 4785 .name = "data_l_s", 4786 .help = "Type #3: data message contains length, ns, nr " 4787 "options", 4788 .next = NEXT(item_l2tpv2_type_data_l_s), 4789 .call = parse_vc_item_l2tpv2_type, 4790 }, 4791 [ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = { 4792 .name = "length", 4793 .help = "message length", 4794 .next = NEXT(item_l2tpv2_type_data_l_s, 4795 NEXT_ENTRY(COMMON_UNSIGNED), 4796 item_param), 4797 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4798 hdr.type3.length)), 4799 }, 4800 [ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = { 4801 .name = "tunnel_id", 4802 .help = "tunnel identifier", 4803 .next = NEXT(item_l2tpv2_type_data_l_s, 4804 NEXT_ENTRY(COMMON_UNSIGNED), 4805 item_param), 4806 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4807 hdr.type3.tunnel_id)), 4808 }, 4809 [ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = { 4810 .name = "session_id", 4811 .help = "session identifier", 4812 .next = NEXT(item_l2tpv2_type_data_l_s, 4813 NEXT_ENTRY(COMMON_UNSIGNED), 4814 item_param), 4815 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4816 hdr.type3.session_id)), 4817 }, 4818 [ITEM_L2TPV2_MSG_DATA_L_S_NS] = { 4819 .name = "ns", 4820 .help = "sequence number for message", 4821 .next = NEXT(item_l2tpv2_type_data_l_s, 4822 NEXT_ENTRY(COMMON_UNSIGNED), 4823 item_param), 4824 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4825 hdr.type3.ns)), 4826 }, 4827 [ITEM_L2TPV2_MSG_DATA_L_S_NR] = { 4828 .name = "nr", 4829 .help = "sequence number for next receive message", 4830 .next = NEXT(item_l2tpv2_type_data_l_s, 4831 NEXT_ENTRY(COMMON_UNSIGNED), 4832 item_param), 4833 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4834 hdr.type3.nr)), 4835 }, 4836 [ITEM_L2TPV2_TYPE_CTRL] = { 4837 .name = "control", 4838 .help = "Type #3: conrtol message contains length, ns, nr " 4839 "options", 4840 .next = NEXT(item_l2tpv2_type_ctrl), 4841 .call = parse_vc_item_l2tpv2_type, 4842 }, 4843 [ITEM_L2TPV2_MSG_CTRL_LENGTH] = { 4844 .name = "length", 4845 .help = "message length", 4846 .next = NEXT(item_l2tpv2_type_ctrl, 4847 NEXT_ENTRY(COMMON_UNSIGNED), 4848 item_param), 4849 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4850 hdr.type3.length)), 4851 }, 4852 [ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = { 4853 .name = "tunnel_id", 4854 .help = "tunnel identifier", 4855 .next = NEXT(item_l2tpv2_type_ctrl, 4856 NEXT_ENTRY(COMMON_UNSIGNED), 4857 item_param), 4858 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4859 hdr.type3.tunnel_id)), 4860 }, 4861 [ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = { 4862 .name = "session_id", 4863 .help = "session identifier", 4864 .next = NEXT(item_l2tpv2_type_ctrl, 4865 NEXT_ENTRY(COMMON_UNSIGNED), 4866 item_param), 4867 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4868 hdr.type3.session_id)), 4869 }, 4870 [ITEM_L2TPV2_MSG_CTRL_NS] = { 4871 .name = "ns", 4872 .help = "sequence number for message", 4873 .next = NEXT(item_l2tpv2_type_ctrl, 4874 NEXT_ENTRY(COMMON_UNSIGNED), 4875 item_param), 4876 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4877 hdr.type3.ns)), 4878 }, 4879 [ITEM_L2TPV2_MSG_CTRL_NR] = { 4880 .name = "nr", 4881 .help = "sequence number for next receive message", 4882 .next = NEXT(item_l2tpv2_type_ctrl, 4883 NEXT_ENTRY(COMMON_UNSIGNED), 4884 item_param), 4885 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 4886 hdr.type3.nr)), 4887 }, 4888 [ITEM_PPP] = { 4889 .name = "ppp", 4890 .help = "match PPP header", 4891 .priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)), 4892 .next = NEXT(item_ppp), 4893 .call = parse_vc, 4894 }, 4895 [ITEM_PPP_ADDR] = { 4896 .name = "addr", 4897 .help = "PPP address", 4898 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED), 4899 item_param), 4900 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)), 4901 }, 4902 [ITEM_PPP_CTRL] = { 4903 .name = "ctrl", 4904 .help = "PPP control", 4905 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED), 4906 item_param), 4907 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)), 4908 }, 4909 [ITEM_PPP_PROTO_ID] = { 4910 .name = "proto_id", 4911 .help = "PPP protocol identifier", 4912 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED), 4913 item_param), 4914 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, 4915 hdr.proto_id)), 4916 }, 4917 /* Validate/create actions. */ 4918 [ACTIONS] = { 4919 .name = "actions", 4920 .help = "submit a list of associated actions", 4921 .next = NEXT(next_action), 4922 .call = parse_vc, 4923 }, 4924 [ACTION_NEXT] = { 4925 .name = "/", 4926 .help = "specify next action", 4927 .next = NEXT(next_action), 4928 }, 4929 [ACTION_END] = { 4930 .name = "end", 4931 .help = "end list of actions", 4932 .priv = PRIV_ACTION(END, 0), 4933 .call = parse_vc, 4934 }, 4935 [ACTION_VOID] = { 4936 .name = "void", 4937 .help = "no-op action", 4938 .priv = PRIV_ACTION(VOID, 0), 4939 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 4940 .call = parse_vc, 4941 }, 4942 [ACTION_PASSTHRU] = { 4943 .name = "passthru", 4944 .help = "let subsequent rule process matched packets", 4945 .priv = PRIV_ACTION(PASSTHRU, 0), 4946 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 4947 .call = parse_vc, 4948 }, 4949 [ACTION_JUMP] = { 4950 .name = "jump", 4951 .help = "redirect traffic to a given group", 4952 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)), 4953 .next = NEXT(action_jump), 4954 .call = parse_vc, 4955 }, 4956 [ACTION_JUMP_GROUP] = { 4957 .name = "group", 4958 .help = "group to redirect traffic to", 4959 .next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)), 4960 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)), 4961 .call = parse_vc_conf, 4962 }, 4963 [ACTION_MARK] = { 4964 .name = "mark", 4965 .help = "attach 32 bit value to packets", 4966 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)), 4967 .next = NEXT(action_mark), 4968 .call = parse_vc, 4969 }, 4970 [ACTION_MARK_ID] = { 4971 .name = "id", 4972 .help = "32 bit value to return with packets", 4973 .next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)), 4974 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)), 4975 .call = parse_vc_conf, 4976 }, 4977 [ACTION_FLAG] = { 4978 .name = "flag", 4979 .help = "flag packets", 4980 .priv = PRIV_ACTION(FLAG, 0), 4981 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 4982 .call = parse_vc, 4983 }, 4984 [ACTION_QUEUE] = { 4985 .name = "queue", 4986 .help = "assign packets to a given queue index", 4987 .priv = PRIV_ACTION(QUEUE, 4988 sizeof(struct rte_flow_action_queue)), 4989 .next = NEXT(action_queue), 4990 .call = parse_vc, 4991 }, 4992 [ACTION_QUEUE_INDEX] = { 4993 .name = "index", 4994 .help = "queue index to use", 4995 .next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)), 4996 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)), 4997 .call = parse_vc_conf, 4998 }, 4999 [ACTION_DROP] = { 5000 .name = "drop", 5001 .help = "drop packets (note: passthru has priority)", 5002 .priv = PRIV_ACTION(DROP, 0), 5003 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5004 .call = parse_vc, 5005 }, 5006 [ACTION_COUNT] = { 5007 .name = "count", 5008 .help = "enable counters for this rule", 5009 .priv = PRIV_ACTION(COUNT, 5010 sizeof(struct rte_flow_action_count)), 5011 .next = NEXT(action_count), 5012 .call = parse_vc, 5013 }, 5014 [ACTION_COUNT_ID] = { 5015 .name = "identifier", 5016 .help = "counter identifier to use", 5017 .next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)), 5018 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)), 5019 .call = parse_vc_conf, 5020 }, 5021 [ACTION_RSS] = { 5022 .name = "rss", 5023 .help = "spread packets among several queues", 5024 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)), 5025 .next = NEXT(action_rss), 5026 .call = parse_vc_action_rss, 5027 }, 5028 [ACTION_RSS_FUNC] = { 5029 .name = "func", 5030 .help = "RSS hash function to apply", 5031 .next = NEXT(action_rss, 5032 NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT, 5033 ACTION_RSS_FUNC_TOEPLITZ, 5034 ACTION_RSS_FUNC_SIMPLE_XOR, 5035 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)), 5036 }, 5037 [ACTION_RSS_FUNC_DEFAULT] = { 5038 .name = "default", 5039 .help = "default hash function", 5040 .call = parse_vc_action_rss_func, 5041 }, 5042 [ACTION_RSS_FUNC_TOEPLITZ] = { 5043 .name = "toeplitz", 5044 .help = "Toeplitz hash function", 5045 .call = parse_vc_action_rss_func, 5046 }, 5047 [ACTION_RSS_FUNC_SIMPLE_XOR] = { 5048 .name = "simple_xor", 5049 .help = "simple XOR hash function", 5050 .call = parse_vc_action_rss_func, 5051 }, 5052 [ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = { 5053 .name = "symmetric_toeplitz", 5054 .help = "Symmetric Toeplitz hash function", 5055 .call = parse_vc_action_rss_func, 5056 }, 5057 [ACTION_RSS_LEVEL] = { 5058 .name = "level", 5059 .help = "encapsulation level for \"types\"", 5060 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)), 5061 .args = ARGS(ARGS_ENTRY_ARB 5062 (offsetof(struct action_rss_data, conf) + 5063 offsetof(struct rte_flow_action_rss, level), 5064 sizeof(((struct rte_flow_action_rss *)0)-> 5065 level))), 5066 }, 5067 [ACTION_RSS_TYPES] = { 5068 .name = "types", 5069 .help = "specific RSS hash types", 5070 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)), 5071 }, 5072 [ACTION_RSS_TYPE] = { 5073 .name = "{type}", 5074 .help = "RSS hash type", 5075 .call = parse_vc_action_rss_type, 5076 .comp = comp_vc_action_rss_type, 5077 }, 5078 [ACTION_RSS_KEY] = { 5079 .name = "key", 5080 .help = "RSS hash key", 5081 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)), 5082 .args = ARGS(ARGS_ENTRY_ARB 5083 (offsetof(struct action_rss_data, conf) + 5084 offsetof(struct rte_flow_action_rss, key), 5085 sizeof(((struct rte_flow_action_rss *)0)->key)), 5086 ARGS_ENTRY_ARB 5087 (offsetof(struct action_rss_data, conf) + 5088 offsetof(struct rte_flow_action_rss, key_len), 5089 sizeof(((struct rte_flow_action_rss *)0)-> 5090 key_len)), 5091 ARGS_ENTRY(struct action_rss_data, key)), 5092 }, 5093 [ACTION_RSS_KEY_LEN] = { 5094 .name = "key_len", 5095 .help = "RSS hash key length in bytes", 5096 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)), 5097 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED 5098 (offsetof(struct action_rss_data, conf) + 5099 offsetof(struct rte_flow_action_rss, key_len), 5100 sizeof(((struct rte_flow_action_rss *)0)-> 5101 key_len), 5102 0, 5103 RSS_HASH_KEY_LENGTH)), 5104 }, 5105 [ACTION_RSS_QUEUES] = { 5106 .name = "queues", 5107 .help = "queue indices to use", 5108 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)), 5109 .call = parse_vc_conf, 5110 }, 5111 [ACTION_RSS_QUEUE] = { 5112 .name = "{queue}", 5113 .help = "queue index", 5114 .call = parse_vc_action_rss_queue, 5115 .comp = comp_vc_action_rss_queue, 5116 }, 5117 [ACTION_PF] = { 5118 .name = "pf", 5119 .help = "direct traffic to physical function", 5120 .priv = PRIV_ACTION(PF, 0), 5121 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5122 .call = parse_vc, 5123 }, 5124 [ACTION_VF] = { 5125 .name = "vf", 5126 .help = "direct traffic to a virtual function ID", 5127 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)), 5128 .next = NEXT(action_vf), 5129 .call = parse_vc, 5130 }, 5131 [ACTION_VF_ORIGINAL] = { 5132 .name = "original", 5133 .help = "use original VF ID if possible", 5134 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)), 5135 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf, 5136 original, 1)), 5137 .call = parse_vc_conf, 5138 }, 5139 [ACTION_VF_ID] = { 5140 .name = "id", 5141 .help = "VF ID", 5142 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)), 5143 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)), 5144 .call = parse_vc_conf, 5145 }, 5146 [ACTION_PHY_PORT] = { 5147 .name = "phy_port", 5148 .help = "direct packets to physical port index", 5149 .priv = PRIV_ACTION(PHY_PORT, 5150 sizeof(struct rte_flow_action_phy_port)), 5151 .next = NEXT(action_phy_port), 5152 .call = parse_vc, 5153 }, 5154 [ACTION_PHY_PORT_ORIGINAL] = { 5155 .name = "original", 5156 .help = "use original port index if possible", 5157 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_BOOLEAN)), 5158 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_phy_port, 5159 original, 1)), 5160 .call = parse_vc_conf, 5161 }, 5162 [ACTION_PHY_PORT_INDEX] = { 5163 .name = "index", 5164 .help = "physical port index", 5165 .next = NEXT(action_phy_port, NEXT_ENTRY(COMMON_UNSIGNED)), 5166 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_phy_port, 5167 index)), 5168 .call = parse_vc_conf, 5169 }, 5170 [ACTION_PORT_ID] = { 5171 .name = "port_id", 5172 .help = "direct matching traffic to a given DPDK port ID", 5173 .priv = PRIV_ACTION(PORT_ID, 5174 sizeof(struct rte_flow_action_port_id)), 5175 .next = NEXT(action_port_id), 5176 .call = parse_vc, 5177 }, 5178 [ACTION_PORT_ID_ORIGINAL] = { 5179 .name = "original", 5180 .help = "use original DPDK port ID if possible", 5181 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)), 5182 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id, 5183 original, 1)), 5184 .call = parse_vc_conf, 5185 }, 5186 [ACTION_PORT_ID_ID] = { 5187 .name = "id", 5188 .help = "DPDK port ID", 5189 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)), 5190 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)), 5191 .call = parse_vc_conf, 5192 }, 5193 [ACTION_METER] = { 5194 .name = "meter", 5195 .help = "meter the directed packets at given id", 5196 .priv = PRIV_ACTION(METER, 5197 sizeof(struct rte_flow_action_meter)), 5198 .next = NEXT(action_meter), 5199 .call = parse_vc, 5200 }, 5201 [ACTION_METER_COLOR] = { 5202 .name = "color", 5203 .help = "meter color for the packets", 5204 .priv = PRIV_ACTION(METER_COLOR, 5205 sizeof(struct rte_flow_action_meter_color)), 5206 .next = NEXT(action_meter_color), 5207 .call = parse_vc, 5208 }, 5209 [ACTION_METER_COLOR_TYPE] = { 5210 .name = "type", 5211 .help = "specific meter color", 5212 .next = NEXT(NEXT_ENTRY(ACTION_NEXT), 5213 NEXT_ENTRY(ACTION_METER_COLOR_GREEN, 5214 ACTION_METER_COLOR_YELLOW, 5215 ACTION_METER_COLOR_RED)), 5216 }, 5217 [ACTION_METER_COLOR_GREEN] = { 5218 .name = "green", 5219 .help = "meter color green", 5220 .call = parse_vc_action_meter_color_type, 5221 }, 5222 [ACTION_METER_COLOR_YELLOW] = { 5223 .name = "yellow", 5224 .help = "meter color yellow", 5225 .call = parse_vc_action_meter_color_type, 5226 }, 5227 [ACTION_METER_COLOR_RED] = { 5228 .name = "red", 5229 .help = "meter color red", 5230 .call = parse_vc_action_meter_color_type, 5231 }, 5232 [ACTION_METER_ID] = { 5233 .name = "mtr_id", 5234 .help = "meter id to use", 5235 .next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)), 5236 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)), 5237 .call = parse_vc_conf, 5238 }, 5239 [ACTION_OF_SET_MPLS_TTL] = { 5240 .name = "of_set_mpls_ttl", 5241 .help = "OpenFlow's OFPAT_SET_MPLS_TTL", 5242 .priv = PRIV_ACTION 5243 (OF_SET_MPLS_TTL, 5244 sizeof(struct rte_flow_action_of_set_mpls_ttl)), 5245 .next = NEXT(action_of_set_mpls_ttl), 5246 .call = parse_vc, 5247 }, 5248 [ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = { 5249 .name = "mpls_ttl", 5250 .help = "MPLS TTL", 5251 .next = NEXT(action_of_set_mpls_ttl, 5252 NEXT_ENTRY(COMMON_UNSIGNED)), 5253 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl, 5254 mpls_ttl)), 5255 .call = parse_vc_conf, 5256 }, 5257 [ACTION_OF_DEC_MPLS_TTL] = { 5258 .name = "of_dec_mpls_ttl", 5259 .help = "OpenFlow's OFPAT_DEC_MPLS_TTL", 5260 .priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0), 5261 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5262 .call = parse_vc, 5263 }, 5264 [ACTION_OF_SET_NW_TTL] = { 5265 .name = "of_set_nw_ttl", 5266 .help = "OpenFlow's OFPAT_SET_NW_TTL", 5267 .priv = PRIV_ACTION 5268 (OF_SET_NW_TTL, 5269 sizeof(struct rte_flow_action_of_set_nw_ttl)), 5270 .next = NEXT(action_of_set_nw_ttl), 5271 .call = parse_vc, 5272 }, 5273 [ACTION_OF_SET_NW_TTL_NW_TTL] = { 5274 .name = "nw_ttl", 5275 .help = "IP TTL", 5276 .next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(COMMON_UNSIGNED)), 5277 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl, 5278 nw_ttl)), 5279 .call = parse_vc_conf, 5280 }, 5281 [ACTION_OF_DEC_NW_TTL] = { 5282 .name = "of_dec_nw_ttl", 5283 .help = "OpenFlow's OFPAT_DEC_NW_TTL", 5284 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0), 5285 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5286 .call = parse_vc, 5287 }, 5288 [ACTION_OF_COPY_TTL_OUT] = { 5289 .name = "of_copy_ttl_out", 5290 .help = "OpenFlow's OFPAT_COPY_TTL_OUT", 5291 .priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0), 5292 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5293 .call = parse_vc, 5294 }, 5295 [ACTION_OF_COPY_TTL_IN] = { 5296 .name = "of_copy_ttl_in", 5297 .help = "OpenFlow's OFPAT_COPY_TTL_IN", 5298 .priv = PRIV_ACTION(OF_COPY_TTL_IN, 0), 5299 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5300 .call = parse_vc, 5301 }, 5302 [ACTION_OF_POP_VLAN] = { 5303 .name = "of_pop_vlan", 5304 .help = "OpenFlow's OFPAT_POP_VLAN", 5305 .priv = PRIV_ACTION(OF_POP_VLAN, 0), 5306 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5307 .call = parse_vc, 5308 }, 5309 [ACTION_OF_PUSH_VLAN] = { 5310 .name = "of_push_vlan", 5311 .help = "OpenFlow's OFPAT_PUSH_VLAN", 5312 .priv = PRIV_ACTION 5313 (OF_PUSH_VLAN, 5314 sizeof(struct rte_flow_action_of_push_vlan)), 5315 .next = NEXT(action_of_push_vlan), 5316 .call = parse_vc, 5317 }, 5318 [ACTION_OF_PUSH_VLAN_ETHERTYPE] = { 5319 .name = "ethertype", 5320 .help = "EtherType", 5321 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)), 5322 .args = ARGS(ARGS_ENTRY_HTON 5323 (struct rte_flow_action_of_push_vlan, 5324 ethertype)), 5325 .call = parse_vc_conf, 5326 }, 5327 [ACTION_OF_SET_VLAN_VID] = { 5328 .name = "of_set_vlan_vid", 5329 .help = "OpenFlow's OFPAT_SET_VLAN_VID", 5330 .priv = PRIV_ACTION 5331 (OF_SET_VLAN_VID, 5332 sizeof(struct rte_flow_action_of_set_vlan_vid)), 5333 .next = NEXT(action_of_set_vlan_vid), 5334 .call = parse_vc, 5335 }, 5336 [ACTION_OF_SET_VLAN_VID_VLAN_VID] = { 5337 .name = "vlan_vid", 5338 .help = "VLAN id", 5339 .next = NEXT(action_of_set_vlan_vid, 5340 NEXT_ENTRY(COMMON_UNSIGNED)), 5341 .args = ARGS(ARGS_ENTRY_HTON 5342 (struct rte_flow_action_of_set_vlan_vid, 5343 vlan_vid)), 5344 .call = parse_vc_conf, 5345 }, 5346 [ACTION_OF_SET_VLAN_PCP] = { 5347 .name = "of_set_vlan_pcp", 5348 .help = "OpenFlow's OFPAT_SET_VLAN_PCP", 5349 .priv = PRIV_ACTION 5350 (OF_SET_VLAN_PCP, 5351 sizeof(struct rte_flow_action_of_set_vlan_pcp)), 5352 .next = NEXT(action_of_set_vlan_pcp), 5353 .call = parse_vc, 5354 }, 5355 [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = { 5356 .name = "vlan_pcp", 5357 .help = "VLAN priority", 5358 .next = NEXT(action_of_set_vlan_pcp, 5359 NEXT_ENTRY(COMMON_UNSIGNED)), 5360 .args = ARGS(ARGS_ENTRY_HTON 5361 (struct rte_flow_action_of_set_vlan_pcp, 5362 vlan_pcp)), 5363 .call = parse_vc_conf, 5364 }, 5365 [ACTION_OF_POP_MPLS] = { 5366 .name = "of_pop_mpls", 5367 .help = "OpenFlow's OFPAT_POP_MPLS", 5368 .priv = PRIV_ACTION(OF_POP_MPLS, 5369 sizeof(struct rte_flow_action_of_pop_mpls)), 5370 .next = NEXT(action_of_pop_mpls), 5371 .call = parse_vc, 5372 }, 5373 [ACTION_OF_POP_MPLS_ETHERTYPE] = { 5374 .name = "ethertype", 5375 .help = "EtherType", 5376 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)), 5377 .args = ARGS(ARGS_ENTRY_HTON 5378 (struct rte_flow_action_of_pop_mpls, 5379 ethertype)), 5380 .call = parse_vc_conf, 5381 }, 5382 [ACTION_OF_PUSH_MPLS] = { 5383 .name = "of_push_mpls", 5384 .help = "OpenFlow's OFPAT_PUSH_MPLS", 5385 .priv = PRIV_ACTION 5386 (OF_PUSH_MPLS, 5387 sizeof(struct rte_flow_action_of_push_mpls)), 5388 .next = NEXT(action_of_push_mpls), 5389 .call = parse_vc, 5390 }, 5391 [ACTION_OF_PUSH_MPLS_ETHERTYPE] = { 5392 .name = "ethertype", 5393 .help = "EtherType", 5394 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)), 5395 .args = ARGS(ARGS_ENTRY_HTON 5396 (struct rte_flow_action_of_push_mpls, 5397 ethertype)), 5398 .call = parse_vc_conf, 5399 }, 5400 [ACTION_VXLAN_ENCAP] = { 5401 .name = "vxlan_encap", 5402 .help = "VXLAN encapsulation, uses configuration set by \"set" 5403 " vxlan\"", 5404 .priv = PRIV_ACTION(VXLAN_ENCAP, 5405 sizeof(struct action_vxlan_encap_data)), 5406 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5407 .call = parse_vc_action_vxlan_encap, 5408 }, 5409 [ACTION_VXLAN_DECAP] = { 5410 .name = "vxlan_decap", 5411 .help = "Performs a decapsulation action by stripping all" 5412 " headers of the VXLAN tunnel network overlay from the" 5413 " matched flow.", 5414 .priv = PRIV_ACTION(VXLAN_DECAP, 0), 5415 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5416 .call = parse_vc, 5417 }, 5418 [ACTION_NVGRE_ENCAP] = { 5419 .name = "nvgre_encap", 5420 .help = "NVGRE encapsulation, uses configuration set by \"set" 5421 " nvgre\"", 5422 .priv = PRIV_ACTION(NVGRE_ENCAP, 5423 sizeof(struct action_nvgre_encap_data)), 5424 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5425 .call = parse_vc_action_nvgre_encap, 5426 }, 5427 [ACTION_NVGRE_DECAP] = { 5428 .name = "nvgre_decap", 5429 .help = "Performs a decapsulation action by stripping all" 5430 " headers of the NVGRE tunnel network overlay from the" 5431 " matched flow.", 5432 .priv = PRIV_ACTION(NVGRE_DECAP, 0), 5433 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5434 .call = parse_vc, 5435 }, 5436 [ACTION_L2_ENCAP] = { 5437 .name = "l2_encap", 5438 .help = "l2 encap, uses configuration set by" 5439 " \"set l2_encap\"", 5440 .priv = PRIV_ACTION(RAW_ENCAP, 5441 sizeof(struct action_raw_encap_data)), 5442 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5443 .call = parse_vc_action_l2_encap, 5444 }, 5445 [ACTION_L2_DECAP] = { 5446 .name = "l2_decap", 5447 .help = "l2 decap, uses configuration set by" 5448 " \"set l2_decap\"", 5449 .priv = PRIV_ACTION(RAW_DECAP, 5450 sizeof(struct action_raw_decap_data)), 5451 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5452 .call = parse_vc_action_l2_decap, 5453 }, 5454 [ACTION_MPLSOGRE_ENCAP] = { 5455 .name = "mplsogre_encap", 5456 .help = "mplsogre encapsulation, uses configuration set by" 5457 " \"set mplsogre_encap\"", 5458 .priv = PRIV_ACTION(RAW_ENCAP, 5459 sizeof(struct action_raw_encap_data)), 5460 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5461 .call = parse_vc_action_mplsogre_encap, 5462 }, 5463 [ACTION_MPLSOGRE_DECAP] = { 5464 .name = "mplsogre_decap", 5465 .help = "mplsogre decapsulation, uses configuration set by" 5466 " \"set mplsogre_decap\"", 5467 .priv = PRIV_ACTION(RAW_DECAP, 5468 sizeof(struct action_raw_decap_data)), 5469 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5470 .call = parse_vc_action_mplsogre_decap, 5471 }, 5472 [ACTION_MPLSOUDP_ENCAP] = { 5473 .name = "mplsoudp_encap", 5474 .help = "mplsoudp encapsulation, uses configuration set by" 5475 " \"set mplsoudp_encap\"", 5476 .priv = PRIV_ACTION(RAW_ENCAP, 5477 sizeof(struct action_raw_encap_data)), 5478 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5479 .call = parse_vc_action_mplsoudp_encap, 5480 }, 5481 [ACTION_MPLSOUDP_DECAP] = { 5482 .name = "mplsoudp_decap", 5483 .help = "mplsoudp decapsulation, uses configuration set by" 5484 " \"set mplsoudp_decap\"", 5485 .priv = PRIV_ACTION(RAW_DECAP, 5486 sizeof(struct action_raw_decap_data)), 5487 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5488 .call = parse_vc_action_mplsoudp_decap, 5489 }, 5490 [ACTION_SET_IPV4_SRC] = { 5491 .name = "set_ipv4_src", 5492 .help = "Set a new IPv4 source address in the outermost" 5493 " IPv4 header", 5494 .priv = PRIV_ACTION(SET_IPV4_SRC, 5495 sizeof(struct rte_flow_action_set_ipv4)), 5496 .next = NEXT(action_set_ipv4_src), 5497 .call = parse_vc, 5498 }, 5499 [ACTION_SET_IPV4_SRC_IPV4_SRC] = { 5500 .name = "ipv4_addr", 5501 .help = "new IPv4 source address to set", 5502 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)), 5503 .args = ARGS(ARGS_ENTRY_HTON 5504 (struct rte_flow_action_set_ipv4, ipv4_addr)), 5505 .call = parse_vc_conf, 5506 }, 5507 [ACTION_SET_IPV4_DST] = { 5508 .name = "set_ipv4_dst", 5509 .help = "Set a new IPv4 destination address in the outermost" 5510 " IPv4 header", 5511 .priv = PRIV_ACTION(SET_IPV4_DST, 5512 sizeof(struct rte_flow_action_set_ipv4)), 5513 .next = NEXT(action_set_ipv4_dst), 5514 .call = parse_vc, 5515 }, 5516 [ACTION_SET_IPV4_DST_IPV4_DST] = { 5517 .name = "ipv4_addr", 5518 .help = "new IPv4 destination address to set", 5519 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)), 5520 .args = ARGS(ARGS_ENTRY_HTON 5521 (struct rte_flow_action_set_ipv4, ipv4_addr)), 5522 .call = parse_vc_conf, 5523 }, 5524 [ACTION_SET_IPV6_SRC] = { 5525 .name = "set_ipv6_src", 5526 .help = "Set a new IPv6 source address in the outermost" 5527 " IPv6 header", 5528 .priv = PRIV_ACTION(SET_IPV6_SRC, 5529 sizeof(struct rte_flow_action_set_ipv6)), 5530 .next = NEXT(action_set_ipv6_src), 5531 .call = parse_vc, 5532 }, 5533 [ACTION_SET_IPV6_SRC_IPV6_SRC] = { 5534 .name = "ipv6_addr", 5535 .help = "new IPv6 source address to set", 5536 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)), 5537 .args = ARGS(ARGS_ENTRY_HTON 5538 (struct rte_flow_action_set_ipv6, ipv6_addr)), 5539 .call = parse_vc_conf, 5540 }, 5541 [ACTION_SET_IPV6_DST] = { 5542 .name = "set_ipv6_dst", 5543 .help = "Set a new IPv6 destination address in the outermost" 5544 " IPv6 header", 5545 .priv = PRIV_ACTION(SET_IPV6_DST, 5546 sizeof(struct rte_flow_action_set_ipv6)), 5547 .next = NEXT(action_set_ipv6_dst), 5548 .call = parse_vc, 5549 }, 5550 [ACTION_SET_IPV6_DST_IPV6_DST] = { 5551 .name = "ipv6_addr", 5552 .help = "new IPv6 destination address to set", 5553 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)), 5554 .args = ARGS(ARGS_ENTRY_HTON 5555 (struct rte_flow_action_set_ipv6, ipv6_addr)), 5556 .call = parse_vc_conf, 5557 }, 5558 [ACTION_SET_TP_SRC] = { 5559 .name = "set_tp_src", 5560 .help = "set a new source port number in the outermost" 5561 " TCP/UDP header", 5562 .priv = PRIV_ACTION(SET_TP_SRC, 5563 sizeof(struct rte_flow_action_set_tp)), 5564 .next = NEXT(action_set_tp_src), 5565 .call = parse_vc, 5566 }, 5567 [ACTION_SET_TP_SRC_TP_SRC] = { 5568 .name = "port", 5569 .help = "new source port number to set", 5570 .next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)), 5571 .args = ARGS(ARGS_ENTRY_HTON 5572 (struct rte_flow_action_set_tp, port)), 5573 .call = parse_vc_conf, 5574 }, 5575 [ACTION_SET_TP_DST] = { 5576 .name = "set_tp_dst", 5577 .help = "set a new destination port number in the outermost" 5578 " TCP/UDP header", 5579 .priv = PRIV_ACTION(SET_TP_DST, 5580 sizeof(struct rte_flow_action_set_tp)), 5581 .next = NEXT(action_set_tp_dst), 5582 .call = parse_vc, 5583 }, 5584 [ACTION_SET_TP_DST_TP_DST] = { 5585 .name = "port", 5586 .help = "new destination port number to set", 5587 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)), 5588 .args = ARGS(ARGS_ENTRY_HTON 5589 (struct rte_flow_action_set_tp, port)), 5590 .call = parse_vc_conf, 5591 }, 5592 [ACTION_MAC_SWAP] = { 5593 .name = "mac_swap", 5594 .help = "Swap the source and destination MAC addresses" 5595 " in the outermost Ethernet header", 5596 .priv = PRIV_ACTION(MAC_SWAP, 0), 5597 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5598 .call = parse_vc, 5599 }, 5600 [ACTION_DEC_TTL] = { 5601 .name = "dec_ttl", 5602 .help = "decrease network TTL if available", 5603 .priv = PRIV_ACTION(DEC_TTL, 0), 5604 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5605 .call = parse_vc, 5606 }, 5607 [ACTION_SET_TTL] = { 5608 .name = "set_ttl", 5609 .help = "set ttl value", 5610 .priv = PRIV_ACTION(SET_TTL, 5611 sizeof(struct rte_flow_action_set_ttl)), 5612 .next = NEXT(action_set_ttl), 5613 .call = parse_vc, 5614 }, 5615 [ACTION_SET_TTL_TTL] = { 5616 .name = "ttl_value", 5617 .help = "new ttl value to set", 5618 .next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)), 5619 .args = ARGS(ARGS_ENTRY_HTON 5620 (struct rte_flow_action_set_ttl, ttl_value)), 5621 .call = parse_vc_conf, 5622 }, 5623 [ACTION_SET_MAC_SRC] = { 5624 .name = "set_mac_src", 5625 .help = "set source mac address", 5626 .priv = PRIV_ACTION(SET_MAC_SRC, 5627 sizeof(struct rte_flow_action_set_mac)), 5628 .next = NEXT(action_set_mac_src), 5629 .call = parse_vc, 5630 }, 5631 [ACTION_SET_MAC_SRC_MAC_SRC] = { 5632 .name = "mac_addr", 5633 .help = "new source mac address", 5634 .next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)), 5635 .args = ARGS(ARGS_ENTRY_HTON 5636 (struct rte_flow_action_set_mac, mac_addr)), 5637 .call = parse_vc_conf, 5638 }, 5639 [ACTION_SET_MAC_DST] = { 5640 .name = "set_mac_dst", 5641 .help = "set destination mac address", 5642 .priv = PRIV_ACTION(SET_MAC_DST, 5643 sizeof(struct rte_flow_action_set_mac)), 5644 .next = NEXT(action_set_mac_dst), 5645 .call = parse_vc, 5646 }, 5647 [ACTION_SET_MAC_DST_MAC_DST] = { 5648 .name = "mac_addr", 5649 .help = "new destination mac address to set", 5650 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)), 5651 .args = ARGS(ARGS_ENTRY_HTON 5652 (struct rte_flow_action_set_mac, mac_addr)), 5653 .call = parse_vc_conf, 5654 }, 5655 [ACTION_INC_TCP_SEQ] = { 5656 .name = "inc_tcp_seq", 5657 .help = "increase TCP sequence number", 5658 .priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)), 5659 .next = NEXT(action_inc_tcp_seq), 5660 .call = parse_vc, 5661 }, 5662 [ACTION_INC_TCP_SEQ_VALUE] = { 5663 .name = "value", 5664 .help = "the value to increase TCP sequence number by", 5665 .next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)), 5666 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)), 5667 .call = parse_vc_conf, 5668 }, 5669 [ACTION_DEC_TCP_SEQ] = { 5670 .name = "dec_tcp_seq", 5671 .help = "decrease TCP sequence number", 5672 .priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)), 5673 .next = NEXT(action_dec_tcp_seq), 5674 .call = parse_vc, 5675 }, 5676 [ACTION_DEC_TCP_SEQ_VALUE] = { 5677 .name = "value", 5678 .help = "the value to decrease TCP sequence number by", 5679 .next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)), 5680 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)), 5681 .call = parse_vc_conf, 5682 }, 5683 [ACTION_INC_TCP_ACK] = { 5684 .name = "inc_tcp_ack", 5685 .help = "increase TCP acknowledgment number", 5686 .priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)), 5687 .next = NEXT(action_inc_tcp_ack), 5688 .call = parse_vc, 5689 }, 5690 [ACTION_INC_TCP_ACK_VALUE] = { 5691 .name = "value", 5692 .help = "the value to increase TCP acknowledgment number by", 5693 .next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)), 5694 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)), 5695 .call = parse_vc_conf, 5696 }, 5697 [ACTION_DEC_TCP_ACK] = { 5698 .name = "dec_tcp_ack", 5699 .help = "decrease TCP acknowledgment number", 5700 .priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)), 5701 .next = NEXT(action_dec_tcp_ack), 5702 .call = parse_vc, 5703 }, 5704 [ACTION_DEC_TCP_ACK_VALUE] = { 5705 .name = "value", 5706 .help = "the value to decrease TCP acknowledgment number by", 5707 .next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)), 5708 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)), 5709 .call = parse_vc_conf, 5710 }, 5711 [ACTION_RAW_ENCAP] = { 5712 .name = "raw_encap", 5713 .help = "encapsulation data, defined by set raw_encap", 5714 .priv = PRIV_ACTION(RAW_ENCAP, 5715 sizeof(struct action_raw_encap_data)), 5716 .next = NEXT(action_raw_encap), 5717 .call = parse_vc_action_raw_encap, 5718 }, 5719 [ACTION_RAW_ENCAP_INDEX] = { 5720 .name = "index", 5721 .help = "the index of raw_encap_confs", 5722 .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)), 5723 }, 5724 [ACTION_RAW_ENCAP_INDEX_VALUE] = { 5725 .name = "{index}", 5726 .type = "UNSIGNED", 5727 .help = "unsigned integer value", 5728 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5729 .call = parse_vc_action_raw_encap_index, 5730 .comp = comp_set_raw_index, 5731 }, 5732 [ACTION_RAW_DECAP] = { 5733 .name = "raw_decap", 5734 .help = "decapsulation data, defined by set raw_encap", 5735 .priv = PRIV_ACTION(RAW_DECAP, 5736 sizeof(struct action_raw_decap_data)), 5737 .next = NEXT(action_raw_decap), 5738 .call = parse_vc_action_raw_decap, 5739 }, 5740 [ACTION_RAW_DECAP_INDEX] = { 5741 .name = "index", 5742 .help = "the index of raw_encap_confs", 5743 .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)), 5744 }, 5745 [ACTION_RAW_DECAP_INDEX_VALUE] = { 5746 .name = "{index}", 5747 .type = "UNSIGNED", 5748 .help = "unsigned integer value", 5749 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 5750 .call = parse_vc_action_raw_decap_index, 5751 .comp = comp_set_raw_index, 5752 }, 5753 [ACTION_MODIFY_FIELD] = { 5754 .name = "modify_field", 5755 .help = "modify destination field with data from source field", 5756 .priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE), 5757 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)), 5758 .call = parse_vc, 5759 }, 5760 [ACTION_MODIFY_FIELD_OP] = { 5761 .name = "op", 5762 .help = "operation type", 5763 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE), 5764 NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)), 5765 .call = parse_vc_conf, 5766 }, 5767 [ACTION_MODIFY_FIELD_OP_VALUE] = { 5768 .name = "{operation}", 5769 .help = "operation type value", 5770 .call = parse_vc_modify_field_op, 5771 .comp = comp_set_modify_field_op, 5772 }, 5773 [ACTION_MODIFY_FIELD_DST_TYPE] = { 5774 .name = "dst_type", 5775 .help = "destination field type", 5776 .next = NEXT(action_modify_field_dst, 5777 NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)), 5778 .call = parse_vc_conf, 5779 }, 5780 [ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = { 5781 .name = "{dst_type}", 5782 .help = "destination field type value", 5783 .call = parse_vc_modify_field_id, 5784 .comp = comp_set_modify_field_id, 5785 }, 5786 [ACTION_MODIFY_FIELD_DST_LEVEL] = { 5787 .name = "dst_level", 5788 .help = "destination field level", 5789 .next = NEXT(action_modify_field_dst, 5790 NEXT_ENTRY(COMMON_UNSIGNED)), 5791 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, 5792 dst.level)), 5793 .call = parse_vc_conf, 5794 }, 5795 [ACTION_MODIFY_FIELD_DST_OFFSET] = { 5796 .name = "dst_offset", 5797 .help = "destination field bit offset", 5798 .next = NEXT(action_modify_field_dst, 5799 NEXT_ENTRY(COMMON_UNSIGNED)), 5800 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, 5801 dst.offset)), 5802 .call = parse_vc_conf, 5803 }, 5804 [ACTION_MODIFY_FIELD_SRC_TYPE] = { 5805 .name = "src_type", 5806 .help = "source field type", 5807 .next = NEXT(action_modify_field_src, 5808 NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)), 5809 .call = parse_vc_conf, 5810 }, 5811 [ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = { 5812 .name = "{src_type}", 5813 .help = "source field type value", 5814 .call = parse_vc_modify_field_id, 5815 .comp = comp_set_modify_field_id, 5816 }, 5817 [ACTION_MODIFY_FIELD_SRC_LEVEL] = { 5818 .name = "src_level", 5819 .help = "source field level", 5820 .next = NEXT(action_modify_field_src, 5821 NEXT_ENTRY(COMMON_UNSIGNED)), 5822 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, 5823 src.level)), 5824 .call = parse_vc_conf, 5825 }, 5826 [ACTION_MODIFY_FIELD_SRC_OFFSET] = { 5827 .name = "src_offset", 5828 .help = "source field bit offset", 5829 .next = NEXT(action_modify_field_src, 5830 NEXT_ENTRY(COMMON_UNSIGNED)), 5831 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, 5832 src.offset)), 5833 .call = parse_vc_conf, 5834 }, 5835 [ACTION_MODIFY_FIELD_SRC_VALUE] = { 5836 .name = "src_value", 5837 .help = "source immediate value", 5838 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH), 5839 NEXT_ENTRY(COMMON_HEX)), 5840 .args = ARGS(ARGS_ENTRY_ARB(0, 0), 5841 ARGS_ENTRY_ARB(0, 0), 5842 ARGS_ENTRY(struct rte_flow_action_modify_field, 5843 src.value)), 5844 .call = parse_vc_conf, 5845 }, 5846 [ACTION_MODIFY_FIELD_SRC_POINTER] = { 5847 .name = "src_ptr", 5848 .help = "pointer to source immediate value", 5849 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH), 5850 NEXT_ENTRY(COMMON_HEX)), 5851 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, 5852 src.pvalue), 5853 ARGS_ENTRY_ARB(0, 0), 5854 ARGS_ENTRY_ARB 5855 (sizeof(struct rte_flow_action_modify_field), 5856 ACTION_MODIFY_PATTERN_SIZE)), 5857 .call = parse_vc_conf, 5858 }, 5859 [ACTION_MODIFY_FIELD_WIDTH] = { 5860 .name = "width", 5861 .help = "number of bits to copy", 5862 .next = NEXT(NEXT_ENTRY(ACTION_NEXT), 5863 NEXT_ENTRY(COMMON_UNSIGNED)), 5864 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, 5865 width)), 5866 .call = parse_vc_conf, 5867 }, 5868 /* Top level command. */ 5869 [SET] = { 5870 .name = "set", 5871 .help = "set raw encap/decap/sample data", 5872 .type = "set raw_encap|raw_decap <index> <pattern>" 5873 " or set sample_actions <index> <action>", 5874 .next = NEXT(NEXT_ENTRY 5875 (SET_RAW_ENCAP, 5876 SET_RAW_DECAP, 5877 SET_SAMPLE_ACTIONS)), 5878 .call = parse_set_init, 5879 }, 5880 /* Sub-level commands. */ 5881 [SET_RAW_ENCAP] = { 5882 .name = "raw_encap", 5883 .help = "set raw encap data", 5884 .next = NEXT(next_set_raw), 5885 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED 5886 (offsetof(struct buffer, port), 5887 sizeof(((struct buffer *)0)->port), 5888 0, RAW_ENCAP_CONFS_MAX_NUM - 1)), 5889 .call = parse_set_raw_encap_decap, 5890 }, 5891 [SET_RAW_DECAP] = { 5892 .name = "raw_decap", 5893 .help = "set raw decap data", 5894 .next = NEXT(next_set_raw), 5895 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED 5896 (offsetof(struct buffer, port), 5897 sizeof(((struct buffer *)0)->port), 5898 0, RAW_ENCAP_CONFS_MAX_NUM - 1)), 5899 .call = parse_set_raw_encap_decap, 5900 }, 5901 [SET_RAW_INDEX] = { 5902 .name = "{index}", 5903 .type = "COMMON_UNSIGNED", 5904 .help = "index of raw_encap/raw_decap data", 5905 .next = NEXT(next_item), 5906 .call = parse_port, 5907 }, 5908 [SET_SAMPLE_INDEX] = { 5909 .name = "{index}", 5910 .type = "UNSIGNED", 5911 .help = "index of sample actions", 5912 .next = NEXT(next_action_sample), 5913 .call = parse_port, 5914 }, 5915 [SET_SAMPLE_ACTIONS] = { 5916 .name = "sample_actions", 5917 .help = "set sample actions list", 5918 .next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)), 5919 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED 5920 (offsetof(struct buffer, port), 5921 sizeof(((struct buffer *)0)->port), 5922 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)), 5923 .call = parse_set_sample_action, 5924 }, 5925 [ACTION_SET_TAG] = { 5926 .name = "set_tag", 5927 .help = "set tag", 5928 .priv = PRIV_ACTION(SET_TAG, 5929 sizeof(struct rte_flow_action_set_tag)), 5930 .next = NEXT(action_set_tag), 5931 .call = parse_vc, 5932 }, 5933 [ACTION_SET_TAG_INDEX] = { 5934 .name = "index", 5935 .help = "index of tag array", 5936 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)), 5937 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)), 5938 .call = parse_vc_conf, 5939 }, 5940 [ACTION_SET_TAG_DATA] = { 5941 .name = "data", 5942 .help = "tag value", 5943 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)), 5944 .args = ARGS(ARGS_ENTRY 5945 (struct rte_flow_action_set_tag, data)), 5946 .call = parse_vc_conf, 5947 }, 5948 [ACTION_SET_TAG_MASK] = { 5949 .name = "mask", 5950 .help = "mask for tag value", 5951 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)), 5952 .args = ARGS(ARGS_ENTRY 5953 (struct rte_flow_action_set_tag, mask)), 5954 .call = parse_vc_conf, 5955 }, 5956 [ACTION_SET_META] = { 5957 .name = "set_meta", 5958 .help = "set metadata", 5959 .priv = PRIV_ACTION(SET_META, 5960 sizeof(struct rte_flow_action_set_meta)), 5961 .next = NEXT(action_set_meta), 5962 .call = parse_vc_action_set_meta, 5963 }, 5964 [ACTION_SET_META_DATA] = { 5965 .name = "data", 5966 .help = "metadata value", 5967 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)), 5968 .args = ARGS(ARGS_ENTRY 5969 (struct rte_flow_action_set_meta, data)), 5970 .call = parse_vc_conf, 5971 }, 5972 [ACTION_SET_META_MASK] = { 5973 .name = "mask", 5974 .help = "mask for metadata value", 5975 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)), 5976 .args = ARGS(ARGS_ENTRY 5977 (struct rte_flow_action_set_meta, mask)), 5978 .call = parse_vc_conf, 5979 }, 5980 [ACTION_SET_IPV4_DSCP] = { 5981 .name = "set_ipv4_dscp", 5982 .help = "set DSCP value", 5983 .priv = PRIV_ACTION(SET_IPV4_DSCP, 5984 sizeof(struct rte_flow_action_set_dscp)), 5985 .next = NEXT(action_set_ipv4_dscp), 5986 .call = parse_vc, 5987 }, 5988 [ACTION_SET_IPV4_DSCP_VALUE] = { 5989 .name = "dscp_value", 5990 .help = "new IPv4 DSCP value to set", 5991 .next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)), 5992 .args = ARGS(ARGS_ENTRY 5993 (struct rte_flow_action_set_dscp, dscp)), 5994 .call = parse_vc_conf, 5995 }, 5996 [ACTION_SET_IPV6_DSCP] = { 5997 .name = "set_ipv6_dscp", 5998 .help = "set DSCP value", 5999 .priv = PRIV_ACTION(SET_IPV6_DSCP, 6000 sizeof(struct rte_flow_action_set_dscp)), 6001 .next = NEXT(action_set_ipv6_dscp), 6002 .call = parse_vc, 6003 }, 6004 [ACTION_SET_IPV6_DSCP_VALUE] = { 6005 .name = "dscp_value", 6006 .help = "new IPv6 DSCP value to set", 6007 .next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)), 6008 .args = ARGS(ARGS_ENTRY 6009 (struct rte_flow_action_set_dscp, dscp)), 6010 .call = parse_vc_conf, 6011 }, 6012 [ACTION_AGE] = { 6013 .name = "age", 6014 .help = "set a specific metadata header", 6015 .next = NEXT(action_age), 6016 .priv = PRIV_ACTION(AGE, 6017 sizeof(struct rte_flow_action_age)), 6018 .call = parse_vc, 6019 }, 6020 [ACTION_AGE_TIMEOUT] = { 6021 .name = "timeout", 6022 .help = "flow age timeout value", 6023 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age, 6024 timeout, 24)), 6025 .next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)), 6026 .call = parse_vc_conf, 6027 }, 6028 [ACTION_SAMPLE] = { 6029 .name = "sample", 6030 .help = "set a sample action", 6031 .next = NEXT(action_sample), 6032 .priv = PRIV_ACTION(SAMPLE, 6033 sizeof(struct action_sample_data)), 6034 .call = parse_vc_action_sample, 6035 }, 6036 [ACTION_SAMPLE_RATIO] = { 6037 .name = "ratio", 6038 .help = "flow sample ratio value", 6039 .next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)), 6040 .args = ARGS(ARGS_ENTRY_ARB 6041 (offsetof(struct action_sample_data, conf) + 6042 offsetof(struct rte_flow_action_sample, ratio), 6043 sizeof(((struct rte_flow_action_sample *)0)-> 6044 ratio))), 6045 }, 6046 [ACTION_SAMPLE_INDEX] = { 6047 .name = "index", 6048 .help = "the index of sample actions list", 6049 .next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)), 6050 }, 6051 [ACTION_SAMPLE_INDEX_VALUE] = { 6052 .name = "{index}", 6053 .type = "COMMON_UNSIGNED", 6054 .help = "unsigned integer value", 6055 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6056 .call = parse_vc_action_sample_index, 6057 .comp = comp_set_sample_index, 6058 }, 6059 [ACTION_CONNTRACK] = { 6060 .name = "conntrack", 6061 .help = "create a conntrack object", 6062 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6063 .priv = PRIV_ACTION(CONNTRACK, 6064 sizeof(struct rte_flow_action_conntrack)), 6065 .call = parse_vc, 6066 }, 6067 [ACTION_CONNTRACK_UPDATE] = { 6068 .name = "conntrack_update", 6069 .help = "update a conntrack object", 6070 .next = NEXT(action_update_conntrack), 6071 .priv = PRIV_ACTION(CONNTRACK, 6072 sizeof(struct rte_flow_modify_conntrack)), 6073 .call = parse_vc, 6074 }, 6075 [ACTION_CONNTRACK_UPDATE_DIR] = { 6076 .name = "dir", 6077 .help = "update a conntrack object direction", 6078 .next = NEXT(action_update_conntrack), 6079 .call = parse_vc_action_conntrack_update, 6080 }, 6081 [ACTION_CONNTRACK_UPDATE_CTX] = { 6082 .name = "ctx", 6083 .help = "update a conntrack object context", 6084 .next = NEXT(action_update_conntrack), 6085 .call = parse_vc_action_conntrack_update, 6086 }, 6087 [ACTION_PORT_REPRESENTOR] = { 6088 .name = "port_representor", 6089 .help = "at embedded switch level, send matching traffic to the given ethdev", 6090 .priv = PRIV_ACTION(PORT_REPRESENTOR, 6091 sizeof(struct rte_flow_action_ethdev)), 6092 .next = NEXT(action_port_representor), 6093 .call = parse_vc, 6094 }, 6095 [ACTION_PORT_REPRESENTOR_PORT_ID] = { 6096 .name = "port_id", 6097 .help = "ethdev port ID", 6098 .next = NEXT(action_port_representor, 6099 NEXT_ENTRY(COMMON_UNSIGNED)), 6100 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev, 6101 port_id)), 6102 .call = parse_vc_conf, 6103 }, 6104 [ACTION_REPRESENTED_PORT] = { 6105 .name = "represented_port", 6106 .help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev", 6107 .priv = PRIV_ACTION(REPRESENTED_PORT, 6108 sizeof(struct rte_flow_action_ethdev)), 6109 .next = NEXT(action_represented_port), 6110 .call = parse_vc, 6111 }, 6112 [ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = { 6113 .name = "ethdev_port_id", 6114 .help = "ethdev port ID", 6115 .next = NEXT(action_represented_port, 6116 NEXT_ENTRY(COMMON_UNSIGNED)), 6117 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev, 6118 port_id)), 6119 .call = parse_vc_conf, 6120 }, 6121 /* Indirect action destroy arguments. */ 6122 [INDIRECT_ACTION_DESTROY_ID] = { 6123 .name = "action_id", 6124 .help = "specify a indirect action id to destroy", 6125 .next = NEXT(next_ia_destroy_attr, 6126 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), 6127 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, 6128 args.ia_destroy.action_id)), 6129 .call = parse_ia_destroy, 6130 }, 6131 /* Indirect action create arguments. */ 6132 [INDIRECT_ACTION_CREATE_ID] = { 6133 .name = "action_id", 6134 .help = "specify a indirect action id to create", 6135 .next = NEXT(next_ia_create_attr, 6136 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), 6137 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)), 6138 }, 6139 [ACTION_INDIRECT] = { 6140 .name = "indirect", 6141 .help = "apply indirect action by id", 6142 .priv = PRIV_ACTION(INDIRECT, 0), 6143 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)), 6144 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))), 6145 .call = parse_vc, 6146 }, 6147 [INDIRECT_ACTION_ID2PTR] = { 6148 .name = "{action_id}", 6149 .type = "INDIRECT_ACTION_ID", 6150 .help = "indirect action id", 6151 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6152 .call = parse_ia_id2ptr, 6153 .comp = comp_none, 6154 }, 6155 [INDIRECT_ACTION_INGRESS] = { 6156 .name = "ingress", 6157 .help = "affect rule to ingress", 6158 .next = NEXT(next_ia_create_attr), 6159 .call = parse_ia, 6160 }, 6161 [INDIRECT_ACTION_EGRESS] = { 6162 .name = "egress", 6163 .help = "affect rule to egress", 6164 .next = NEXT(next_ia_create_attr), 6165 .call = parse_ia, 6166 }, 6167 [INDIRECT_ACTION_TRANSFER] = { 6168 .name = "transfer", 6169 .help = "affect rule to transfer", 6170 .next = NEXT(next_ia_create_attr), 6171 .call = parse_ia, 6172 }, 6173 [INDIRECT_ACTION_SPEC] = { 6174 .name = "action", 6175 .help = "specify action to create indirect handle", 6176 .next = NEXT(next_action), 6177 }, 6178 [ACTION_POL_G] = { 6179 .name = "g_actions", 6180 .help = "submit a list of associated actions for green", 6181 .next = NEXT(next_action), 6182 .call = parse_mp, 6183 }, 6184 [ACTION_POL_Y] = { 6185 .name = "y_actions", 6186 .help = "submit a list of associated actions for yellow", 6187 .next = NEXT(next_action), 6188 }, 6189 [ACTION_POL_R] = { 6190 .name = "r_actions", 6191 .help = "submit a list of associated actions for red", 6192 .next = NEXT(next_action), 6193 }, 6194 6195 /* Top-level command. */ 6196 [ADD] = { 6197 .name = "add", 6198 .type = "port meter policy {port_id} {arg}", 6199 .help = "add port meter policy", 6200 .next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)), 6201 .call = parse_init, 6202 }, 6203 /* Sub-level commands. */ 6204 [ITEM_POL_PORT] = { 6205 .name = "port", 6206 .help = "add port meter policy", 6207 .next = NEXT(NEXT_ENTRY(ITEM_POL_METER)), 6208 }, 6209 [ITEM_POL_METER] = { 6210 .name = "meter", 6211 .help = "add port meter policy", 6212 .next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)), 6213 }, 6214 [ITEM_POL_POLICY] = { 6215 .name = "policy", 6216 .help = "add port meter policy", 6217 .next = NEXT(NEXT_ENTRY(ACTION_POL_R), 6218 NEXT_ENTRY(ACTION_POL_Y), 6219 NEXT_ENTRY(ACTION_POL_G), 6220 NEXT_ENTRY(COMMON_POLICY_ID), 6221 NEXT_ENTRY(COMMON_PORT_ID)), 6222 .args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id), 6223 ARGS_ENTRY(struct buffer, port)), 6224 .call = parse_mp, 6225 }, 6226 }; 6227 6228 /** Remove and return last entry from argument stack. */ 6229 static const struct arg * 6230 pop_args(struct context *ctx) 6231 { 6232 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL; 6233 } 6234 6235 /** Add entry on top of the argument stack. */ 6236 static int 6237 push_args(struct context *ctx, const struct arg *arg) 6238 { 6239 if (ctx->args_num == CTX_STACK_SIZE) 6240 return -1; 6241 ctx->args[ctx->args_num++] = arg; 6242 return 0; 6243 } 6244 6245 /** Spread value into buffer according to bit-mask. */ 6246 static size_t 6247 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg) 6248 { 6249 uint32_t i = arg->size; 6250 uint32_t end = 0; 6251 int sub = 1; 6252 int add = 0; 6253 size_t len = 0; 6254 6255 if (!arg->mask) 6256 return 0; 6257 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 6258 if (!arg->hton) { 6259 i = 0; 6260 end = arg->size; 6261 sub = 0; 6262 add = 1; 6263 } 6264 #endif 6265 while (i != end) { 6266 unsigned int shift = 0; 6267 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub); 6268 6269 for (shift = 0; arg->mask[i] >> shift; ++shift) { 6270 if (!(arg->mask[i] & (1 << shift))) 6271 continue; 6272 ++len; 6273 if (!dst) 6274 continue; 6275 *buf &= ~(1 << shift); 6276 *buf |= (val & 1) << shift; 6277 val >>= 1; 6278 } 6279 i += add; 6280 } 6281 return len; 6282 } 6283 6284 /** Compare a string with a partial one of a given length. */ 6285 static int 6286 strcmp_partial(const char *full, const char *partial, size_t partial_len) 6287 { 6288 int r = strncmp(full, partial, partial_len); 6289 6290 if (r) 6291 return r; 6292 if (strlen(full) <= partial_len) 6293 return 0; 6294 return full[partial_len]; 6295 } 6296 6297 /** 6298 * Parse a prefix length and generate a bit-mask. 6299 * 6300 * Last argument (ctx->args) is retrieved to determine mask size, storage 6301 * location and whether the result must use network byte ordering. 6302 */ 6303 static int 6304 parse_prefix(struct context *ctx, const struct token *token, 6305 const char *str, unsigned int len, 6306 void *buf, unsigned int size) 6307 { 6308 const struct arg *arg = pop_args(ctx); 6309 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff"; 6310 char *end; 6311 uintmax_t u; 6312 unsigned int bytes; 6313 unsigned int extra; 6314 6315 (void)token; 6316 /* Argument is expected. */ 6317 if (!arg) 6318 return -1; 6319 errno = 0; 6320 u = strtoumax(str, &end, 0); 6321 if (errno || (size_t)(end - str) != len) 6322 goto error; 6323 if (arg->mask) { 6324 uintmax_t v = 0; 6325 6326 extra = arg_entry_bf_fill(NULL, 0, arg); 6327 if (u > extra) 6328 goto error; 6329 if (!ctx->object) 6330 return len; 6331 extra -= u; 6332 while (u--) 6333 (v <<= 1, v |= 1); 6334 v <<= extra; 6335 if (!arg_entry_bf_fill(ctx->object, v, arg) || 6336 !arg_entry_bf_fill(ctx->objmask, -1, arg)) 6337 goto error; 6338 return len; 6339 } 6340 bytes = u / 8; 6341 extra = u % 8; 6342 size = arg->size; 6343 if (bytes > size || bytes + !!extra > size) 6344 goto error; 6345 if (!ctx->object) 6346 return len; 6347 buf = (uint8_t *)ctx->object + arg->offset; 6348 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 6349 if (!arg->hton) { 6350 memset((uint8_t *)buf + size - bytes, 0xff, bytes); 6351 memset(buf, 0x00, size - bytes); 6352 if (extra) 6353 ((uint8_t *)buf)[size - bytes - 1] = conv[extra]; 6354 } else 6355 #endif 6356 { 6357 memset(buf, 0xff, bytes); 6358 memset((uint8_t *)buf + bytes, 0x00, size - bytes); 6359 if (extra) 6360 ((uint8_t *)buf)[bytes] = conv[extra]; 6361 } 6362 if (ctx->objmask) 6363 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 6364 return len; 6365 error: 6366 push_args(ctx, arg); 6367 return -1; 6368 } 6369 6370 /** Default parsing function for token name matching. */ 6371 static int 6372 parse_default(struct context *ctx, const struct token *token, 6373 const char *str, unsigned int len, 6374 void *buf, unsigned int size) 6375 { 6376 (void)ctx; 6377 (void)buf; 6378 (void)size; 6379 if (strcmp_partial(token->name, str, len)) 6380 return -1; 6381 return len; 6382 } 6383 6384 /** Parse flow command, initialize output buffer for subsequent tokens. */ 6385 static int 6386 parse_init(struct context *ctx, const struct token *token, 6387 const char *str, unsigned int len, 6388 void *buf, unsigned int size) 6389 { 6390 struct buffer *out = buf; 6391 6392 /* Token name must match. */ 6393 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6394 return -1; 6395 /* Nothing else to do if there is no buffer. */ 6396 if (!out) 6397 return len; 6398 /* Make sure buffer is large enough. */ 6399 if (size < sizeof(*out)) 6400 return -1; 6401 /* Initialize buffer. */ 6402 memset(out, 0x00, sizeof(*out)); 6403 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out)); 6404 ctx->objdata = 0; 6405 ctx->object = out; 6406 ctx->objmask = NULL; 6407 return len; 6408 } 6409 6410 /** Parse tokens for indirect action commands. */ 6411 static int 6412 parse_ia(struct context *ctx, const struct token *token, 6413 const char *str, unsigned int len, 6414 void *buf, unsigned int size) 6415 { 6416 struct buffer *out = buf; 6417 6418 /* Token name must match. */ 6419 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6420 return -1; 6421 /* Nothing else to do if there is no buffer. */ 6422 if (!out) 6423 return len; 6424 if (!out->command) { 6425 if (ctx->curr != INDIRECT_ACTION) 6426 return -1; 6427 if (sizeof(*out) > size) 6428 return -1; 6429 out->command = ctx->curr; 6430 ctx->objdata = 0; 6431 ctx->object = out; 6432 ctx->objmask = NULL; 6433 out->args.vc.data = (uint8_t *)out + size; 6434 return len; 6435 } 6436 switch (ctx->curr) { 6437 case INDIRECT_ACTION_CREATE: 6438 case INDIRECT_ACTION_UPDATE: 6439 out->args.vc.actions = 6440 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 6441 sizeof(double)); 6442 out->args.vc.attr.group = UINT32_MAX; 6443 /* fallthrough */ 6444 case INDIRECT_ACTION_QUERY: 6445 out->command = ctx->curr; 6446 ctx->objdata = 0; 6447 ctx->object = out; 6448 ctx->objmask = NULL; 6449 return len; 6450 case INDIRECT_ACTION_EGRESS: 6451 out->args.vc.attr.egress = 1; 6452 return len; 6453 case INDIRECT_ACTION_INGRESS: 6454 out->args.vc.attr.ingress = 1; 6455 return len; 6456 case INDIRECT_ACTION_TRANSFER: 6457 out->args.vc.attr.transfer = 1; 6458 return len; 6459 default: 6460 return -1; 6461 } 6462 } 6463 6464 6465 /** Parse tokens for indirect action destroy command. */ 6466 static int 6467 parse_ia_destroy(struct context *ctx, const struct token *token, 6468 const char *str, unsigned int len, 6469 void *buf, unsigned int size) 6470 { 6471 struct buffer *out = buf; 6472 uint32_t *action_id; 6473 6474 /* Token name must match. */ 6475 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6476 return -1; 6477 /* Nothing else to do if there is no buffer. */ 6478 if (!out) 6479 return len; 6480 if (!out->command || out->command == INDIRECT_ACTION) { 6481 if (ctx->curr != INDIRECT_ACTION_DESTROY) 6482 return -1; 6483 if (sizeof(*out) > size) 6484 return -1; 6485 out->command = ctx->curr; 6486 ctx->objdata = 0; 6487 ctx->object = out; 6488 ctx->objmask = NULL; 6489 out->args.ia_destroy.action_id = 6490 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 6491 sizeof(double)); 6492 return len; 6493 } 6494 action_id = out->args.ia_destroy.action_id 6495 + out->args.ia_destroy.action_id_n++; 6496 if ((uint8_t *)action_id > (uint8_t *)out + size) 6497 return -1; 6498 ctx->objdata = 0; 6499 ctx->object = action_id; 6500 ctx->objmask = NULL; 6501 return len; 6502 } 6503 6504 /** Parse tokens for meter policy action commands. */ 6505 static int 6506 parse_mp(struct context *ctx, const struct token *token, 6507 const char *str, unsigned int len, 6508 void *buf, unsigned int size) 6509 { 6510 struct buffer *out = buf; 6511 6512 /* Token name must match. */ 6513 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6514 return -1; 6515 /* Nothing else to do if there is no buffer. */ 6516 if (!out) 6517 return len; 6518 if (!out->command) { 6519 if (ctx->curr != ITEM_POL_POLICY) 6520 return -1; 6521 if (sizeof(*out) > size) 6522 return -1; 6523 out->command = ctx->curr; 6524 ctx->objdata = 0; 6525 ctx->object = out; 6526 ctx->objmask = NULL; 6527 out->args.vc.data = (uint8_t *)out + size; 6528 return len; 6529 } 6530 switch (ctx->curr) { 6531 case ACTION_POL_G: 6532 out->args.vc.actions = 6533 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 6534 sizeof(double)); 6535 out->command = ctx->curr; 6536 ctx->objdata = 0; 6537 ctx->object = out; 6538 ctx->objmask = NULL; 6539 return len; 6540 default: 6541 return -1; 6542 } 6543 } 6544 6545 /** Parse tokens for validate/create commands. */ 6546 static int 6547 parse_vc(struct context *ctx, const struct token *token, 6548 const char *str, unsigned int len, 6549 void *buf, unsigned int size) 6550 { 6551 struct buffer *out = buf; 6552 uint8_t *data; 6553 uint32_t data_size; 6554 6555 /* Token name must match. */ 6556 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6557 return -1; 6558 /* Nothing else to do if there is no buffer. */ 6559 if (!out) 6560 return len; 6561 if (!out->command) { 6562 if (ctx->curr != VALIDATE && ctx->curr != CREATE && 6563 ctx->curr != PATTERN_TEMPLATE_CREATE && 6564 ctx->curr != ACTIONS_TEMPLATE_CREATE) 6565 return -1; 6566 if (sizeof(*out) > size) 6567 return -1; 6568 out->command = ctx->curr; 6569 ctx->objdata = 0; 6570 ctx->object = out; 6571 ctx->objmask = NULL; 6572 out->args.vc.data = (uint8_t *)out + size; 6573 return len; 6574 } 6575 ctx->objdata = 0; 6576 switch (ctx->curr) { 6577 default: 6578 ctx->object = &out->args.vc.attr; 6579 break; 6580 case VC_TUNNEL_SET: 6581 case VC_TUNNEL_MATCH: 6582 ctx->object = &out->args.vc.tunnel_ops; 6583 break; 6584 } 6585 ctx->objmask = NULL; 6586 switch (ctx->curr) { 6587 case VC_GROUP: 6588 case VC_PRIORITY: 6589 return len; 6590 case VC_TUNNEL_SET: 6591 out->args.vc.tunnel_ops.enabled = 1; 6592 out->args.vc.tunnel_ops.actions = 1; 6593 return len; 6594 case VC_TUNNEL_MATCH: 6595 out->args.vc.tunnel_ops.enabled = 1; 6596 out->args.vc.tunnel_ops.items = 1; 6597 return len; 6598 case VC_INGRESS: 6599 out->args.vc.attr.ingress = 1; 6600 return len; 6601 case VC_EGRESS: 6602 out->args.vc.attr.egress = 1; 6603 return len; 6604 case VC_TRANSFER: 6605 out->args.vc.attr.transfer = 1; 6606 return len; 6607 case ITEM_PATTERN: 6608 out->args.vc.pattern = 6609 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 6610 sizeof(double)); 6611 ctx->object = out->args.vc.pattern; 6612 ctx->objmask = NULL; 6613 return len; 6614 case ACTIONS: 6615 out->args.vc.actions = 6616 (void *)RTE_ALIGN_CEIL((uintptr_t) 6617 (out->args.vc.pattern + 6618 out->args.vc.pattern_n), 6619 sizeof(double)); 6620 ctx->object = out->args.vc.actions; 6621 ctx->objmask = NULL; 6622 return len; 6623 default: 6624 if (!token->priv) 6625 return -1; 6626 break; 6627 } 6628 if (!out->args.vc.actions) { 6629 const struct parse_item_priv *priv = token->priv; 6630 struct rte_flow_item *item = 6631 out->args.vc.pattern + out->args.vc.pattern_n; 6632 6633 data_size = priv->size * 3; /* spec, last, mask */ 6634 data = (void *)RTE_ALIGN_FLOOR((uintptr_t) 6635 (out->args.vc.data - data_size), 6636 sizeof(double)); 6637 if ((uint8_t *)item + sizeof(*item) > data) 6638 return -1; 6639 *item = (struct rte_flow_item){ 6640 .type = priv->type, 6641 }; 6642 ++out->args.vc.pattern_n; 6643 ctx->object = item; 6644 ctx->objmask = NULL; 6645 } else { 6646 const struct parse_action_priv *priv = token->priv; 6647 struct rte_flow_action *action = 6648 out->args.vc.actions + out->args.vc.actions_n; 6649 6650 data_size = priv->size; /* configuration */ 6651 data = (void *)RTE_ALIGN_FLOOR((uintptr_t) 6652 (out->args.vc.data - data_size), 6653 sizeof(double)); 6654 if ((uint8_t *)action + sizeof(*action) > data) 6655 return -1; 6656 *action = (struct rte_flow_action){ 6657 .type = priv->type, 6658 .conf = data_size ? data : NULL, 6659 }; 6660 ++out->args.vc.actions_n; 6661 ctx->object = action; 6662 ctx->objmask = NULL; 6663 } 6664 memset(data, 0, data_size); 6665 out->args.vc.data = data; 6666 ctx->objdata = data_size; 6667 return len; 6668 } 6669 6670 /** Parse pattern item parameter type. */ 6671 static int 6672 parse_vc_spec(struct context *ctx, const struct token *token, 6673 const char *str, unsigned int len, 6674 void *buf, unsigned int size) 6675 { 6676 struct buffer *out = buf; 6677 struct rte_flow_item *item; 6678 uint32_t data_size; 6679 int index; 6680 int objmask = 0; 6681 6682 (void)size; 6683 /* Token name must match. */ 6684 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6685 return -1; 6686 /* Parse parameter types. */ 6687 switch (ctx->curr) { 6688 static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX); 6689 6690 case ITEM_PARAM_IS: 6691 index = 0; 6692 objmask = 1; 6693 break; 6694 case ITEM_PARAM_SPEC: 6695 index = 0; 6696 break; 6697 case ITEM_PARAM_LAST: 6698 index = 1; 6699 break; 6700 case ITEM_PARAM_PREFIX: 6701 /* Modify next token to expect a prefix. */ 6702 if (ctx->next_num < 2) 6703 return -1; 6704 ctx->next[ctx->next_num - 2] = prefix; 6705 /* Fall through. */ 6706 case ITEM_PARAM_MASK: 6707 index = 2; 6708 break; 6709 default: 6710 return -1; 6711 } 6712 /* Nothing else to do if there is no buffer. */ 6713 if (!out) 6714 return len; 6715 if (!out->args.vc.pattern_n) 6716 return -1; 6717 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1]; 6718 data_size = ctx->objdata / 3; /* spec, last, mask */ 6719 /* Point to selected object. */ 6720 ctx->object = out->args.vc.data + (data_size * index); 6721 if (objmask) { 6722 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */ 6723 item->mask = ctx->objmask; 6724 } else 6725 ctx->objmask = NULL; 6726 /* Update relevant item pointer. */ 6727 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] = 6728 ctx->object; 6729 return len; 6730 } 6731 6732 /** Parse action configuration field. */ 6733 static int 6734 parse_vc_conf(struct context *ctx, const struct token *token, 6735 const char *str, unsigned int len, 6736 void *buf, unsigned int size) 6737 { 6738 struct buffer *out = buf; 6739 6740 (void)size; 6741 /* Token name must match. */ 6742 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6743 return -1; 6744 /* Nothing else to do if there is no buffer. */ 6745 if (!out) 6746 return len; 6747 /* Point to selected object. */ 6748 ctx->object = out->args.vc.data; 6749 ctx->objmask = NULL; 6750 return len; 6751 } 6752 6753 /** Parse eCPRI common header type field. */ 6754 static int 6755 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token, 6756 const char *str, unsigned int len, 6757 void *buf, unsigned int size) 6758 { 6759 struct rte_flow_item_ecpri *ecpri; 6760 struct rte_flow_item_ecpri *ecpri_mask; 6761 struct rte_flow_item *item; 6762 uint32_t data_size; 6763 uint8_t msg_type; 6764 struct buffer *out = buf; 6765 const struct arg *arg; 6766 6767 (void)size; 6768 /* Token name must match. */ 6769 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6770 return -1; 6771 switch (ctx->curr) { 6772 case ITEM_ECPRI_COMMON_TYPE_IQ_DATA: 6773 msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA; 6774 break; 6775 case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL: 6776 msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL; 6777 break; 6778 case ITEM_ECPRI_COMMON_TYPE_DLY_MSR: 6779 msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR; 6780 break; 6781 default: 6782 return -1; 6783 } 6784 if (!ctx->object) 6785 return len; 6786 arg = pop_args(ctx); 6787 if (!arg) 6788 return -1; 6789 ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data; 6790 ecpri->hdr.common.type = msg_type; 6791 data_size = ctx->objdata / 3; /* spec, last, mask */ 6792 ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data + 6793 (data_size * 2)); 6794 ecpri_mask->hdr.common.type = 0xFF; 6795 if (arg->hton) { 6796 ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32); 6797 ecpri_mask->hdr.common.u32 = 6798 rte_cpu_to_be_32(ecpri_mask->hdr.common.u32); 6799 } 6800 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1]; 6801 item->spec = ecpri; 6802 item->mask = ecpri_mask; 6803 return len; 6804 } 6805 6806 /** Parse L2TPv2 common header type field. */ 6807 static int 6808 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token, 6809 const char *str, unsigned int len, 6810 void *buf, unsigned int size) 6811 { 6812 struct rte_flow_item_l2tpv2 *l2tpv2; 6813 struct rte_flow_item_l2tpv2 *l2tpv2_mask; 6814 struct rte_flow_item *item; 6815 uint32_t data_size; 6816 uint16_t msg_type = 0; 6817 struct buffer *out = buf; 6818 const struct arg *arg; 6819 6820 (void)size; 6821 /* Token name must match. */ 6822 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6823 return -1; 6824 switch (ctx->curr) { 6825 case ITEM_L2TPV2_TYPE_DATA: 6826 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA; 6827 break; 6828 case ITEM_L2TPV2_TYPE_DATA_L: 6829 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L; 6830 break; 6831 case ITEM_L2TPV2_TYPE_DATA_S: 6832 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S; 6833 break; 6834 case ITEM_L2TPV2_TYPE_DATA_O: 6835 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O; 6836 break; 6837 case ITEM_L2TPV2_TYPE_DATA_L_S: 6838 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S; 6839 break; 6840 case ITEM_L2TPV2_TYPE_CTRL: 6841 msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL; 6842 break; 6843 default: 6844 return -1; 6845 } 6846 if (!ctx->object) 6847 return len; 6848 arg = pop_args(ctx); 6849 if (!arg) 6850 return -1; 6851 l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data; 6852 l2tpv2->hdr.common.flags_version |= msg_type; 6853 data_size = ctx->objdata / 3; /* spec, last, mask */ 6854 l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data + 6855 (data_size * 2)); 6856 l2tpv2_mask->hdr.common.flags_version = 0xFFFF; 6857 if (arg->hton) { 6858 l2tpv2->hdr.common.flags_version = 6859 rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version); 6860 l2tpv2_mask->hdr.common.flags_version = 6861 rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version); 6862 } 6863 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1]; 6864 item->spec = l2tpv2; 6865 item->mask = l2tpv2_mask; 6866 return len; 6867 } 6868 6869 /** Parse meter color action type. */ 6870 static int 6871 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token, 6872 const char *str, unsigned int len, 6873 void *buf, unsigned int size) 6874 { 6875 struct rte_flow_action *action_data; 6876 struct rte_flow_action_meter_color *conf; 6877 enum rte_color color; 6878 6879 (void)buf; 6880 (void)size; 6881 /* Token name must match. */ 6882 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6883 return -1; 6884 switch (ctx->curr) { 6885 case ACTION_METER_COLOR_GREEN: 6886 color = RTE_COLOR_GREEN; 6887 break; 6888 case ACTION_METER_COLOR_YELLOW: 6889 color = RTE_COLOR_YELLOW; 6890 break; 6891 case ACTION_METER_COLOR_RED: 6892 color = RTE_COLOR_RED; 6893 break; 6894 default: 6895 return -1; 6896 } 6897 6898 if (!ctx->object) 6899 return len; 6900 action_data = ctx->object; 6901 conf = (struct rte_flow_action_meter_color *) 6902 (uintptr_t)(action_data->conf); 6903 conf->color = color; 6904 return len; 6905 } 6906 6907 /** Parse RSS action. */ 6908 static int 6909 parse_vc_action_rss(struct context *ctx, const struct token *token, 6910 const char *str, unsigned int len, 6911 void *buf, unsigned int size) 6912 { 6913 struct buffer *out = buf; 6914 struct rte_flow_action *action; 6915 struct action_rss_data *action_rss_data; 6916 unsigned int i; 6917 int ret; 6918 6919 ret = parse_vc(ctx, token, str, len, buf, size); 6920 if (ret < 0) 6921 return ret; 6922 /* Nothing else to do if there is no buffer. */ 6923 if (!out) 6924 return ret; 6925 if (!out->args.vc.actions_n) 6926 return -1; 6927 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 6928 /* Point to selected object. */ 6929 ctx->object = out->args.vc.data; 6930 ctx->objmask = NULL; 6931 /* Set up default configuration. */ 6932 action_rss_data = ctx->object; 6933 *action_rss_data = (struct action_rss_data){ 6934 .conf = (struct rte_flow_action_rss){ 6935 .func = RTE_ETH_HASH_FUNCTION_DEFAULT, 6936 .level = 0, 6937 .types = rss_hf, 6938 .key_len = 0, 6939 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM), 6940 .key = NULL, 6941 .queue = action_rss_data->queue, 6942 }, 6943 .queue = { 0 }, 6944 }; 6945 for (i = 0; i < action_rss_data->conf.queue_num; ++i) 6946 action_rss_data->queue[i] = i; 6947 action->conf = &action_rss_data->conf; 6948 return ret; 6949 } 6950 6951 /** 6952 * Parse func field for RSS action. 6953 * 6954 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the 6955 * ACTION_RSS_FUNC_* index that called this function. 6956 */ 6957 static int 6958 parse_vc_action_rss_func(struct context *ctx, const struct token *token, 6959 const char *str, unsigned int len, 6960 void *buf, unsigned int size) 6961 { 6962 struct action_rss_data *action_rss_data; 6963 enum rte_eth_hash_function func; 6964 6965 (void)buf; 6966 (void)size; 6967 /* Token name must match. */ 6968 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6969 return -1; 6970 switch (ctx->curr) { 6971 case ACTION_RSS_FUNC_DEFAULT: 6972 func = RTE_ETH_HASH_FUNCTION_DEFAULT; 6973 break; 6974 case ACTION_RSS_FUNC_TOEPLITZ: 6975 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ; 6976 break; 6977 case ACTION_RSS_FUNC_SIMPLE_XOR: 6978 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR; 6979 break; 6980 case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ: 6981 func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ; 6982 break; 6983 default: 6984 return -1; 6985 } 6986 if (!ctx->object) 6987 return len; 6988 action_rss_data = ctx->object; 6989 action_rss_data->conf.func = func; 6990 return len; 6991 } 6992 6993 /** 6994 * Parse type field for RSS action. 6995 * 6996 * Valid tokens are type field names and the "end" token. 6997 */ 6998 static int 6999 parse_vc_action_rss_type(struct context *ctx, const struct token *token, 7000 const char *str, unsigned int len, 7001 void *buf, unsigned int size) 7002 { 7003 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE); 7004 struct action_rss_data *action_rss_data; 7005 unsigned int i; 7006 7007 (void)token; 7008 (void)buf; 7009 (void)size; 7010 if (ctx->curr != ACTION_RSS_TYPE) 7011 return -1; 7012 if (!(ctx->objdata >> 16) && ctx->object) { 7013 action_rss_data = ctx->object; 7014 action_rss_data->conf.types = 0; 7015 } 7016 if (!strcmp_partial("end", str, len)) { 7017 ctx->objdata &= 0xffff; 7018 return len; 7019 } 7020 for (i = 0; rss_type_table[i].str; ++i) 7021 if (!strcmp_partial(rss_type_table[i].str, str, len)) 7022 break; 7023 if (!rss_type_table[i].str) 7024 return -1; 7025 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff); 7026 /* Repeat token. */ 7027 if (ctx->next_num == RTE_DIM(ctx->next)) 7028 return -1; 7029 ctx->next[ctx->next_num++] = next; 7030 if (!ctx->object) 7031 return len; 7032 action_rss_data = ctx->object; 7033 action_rss_data->conf.types |= rss_type_table[i].rss_type; 7034 return len; 7035 } 7036 7037 /** 7038 * Parse queue field for RSS action. 7039 * 7040 * Valid tokens are queue indices and the "end" token. 7041 */ 7042 static int 7043 parse_vc_action_rss_queue(struct context *ctx, const struct token *token, 7044 const char *str, unsigned int len, 7045 void *buf, unsigned int size) 7046 { 7047 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE); 7048 struct action_rss_data *action_rss_data; 7049 const struct arg *arg; 7050 int ret; 7051 int i; 7052 7053 (void)token; 7054 (void)buf; 7055 (void)size; 7056 if (ctx->curr != ACTION_RSS_QUEUE) 7057 return -1; 7058 i = ctx->objdata >> 16; 7059 if (!strcmp_partial("end", str, len)) { 7060 ctx->objdata &= 0xffff; 7061 goto end; 7062 } 7063 if (i >= ACTION_RSS_QUEUE_NUM) 7064 return -1; 7065 arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) + 7066 i * sizeof(action_rss_data->queue[i]), 7067 sizeof(action_rss_data->queue[i])); 7068 if (push_args(ctx, arg)) 7069 return -1; 7070 ret = parse_int(ctx, token, str, len, NULL, 0); 7071 if (ret < 0) { 7072 pop_args(ctx); 7073 return -1; 7074 } 7075 ++i; 7076 ctx->objdata = i << 16 | (ctx->objdata & 0xffff); 7077 /* Repeat token. */ 7078 if (ctx->next_num == RTE_DIM(ctx->next)) 7079 return -1; 7080 ctx->next[ctx->next_num++] = next; 7081 end: 7082 if (!ctx->object) 7083 return len; 7084 action_rss_data = ctx->object; 7085 action_rss_data->conf.queue_num = i; 7086 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL; 7087 return len; 7088 } 7089 7090 /** Setup VXLAN encap configuration. */ 7091 static int 7092 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data) 7093 { 7094 /* Set up default configuration. */ 7095 *action_vxlan_encap_data = (struct action_vxlan_encap_data){ 7096 .conf = (struct rte_flow_action_vxlan_encap){ 7097 .definition = action_vxlan_encap_data->items, 7098 }, 7099 .items = { 7100 { 7101 .type = RTE_FLOW_ITEM_TYPE_ETH, 7102 .spec = &action_vxlan_encap_data->item_eth, 7103 .mask = &rte_flow_item_eth_mask, 7104 }, 7105 { 7106 .type = RTE_FLOW_ITEM_TYPE_VLAN, 7107 .spec = &action_vxlan_encap_data->item_vlan, 7108 .mask = &rte_flow_item_vlan_mask, 7109 }, 7110 { 7111 .type = RTE_FLOW_ITEM_TYPE_IPV4, 7112 .spec = &action_vxlan_encap_data->item_ipv4, 7113 .mask = &rte_flow_item_ipv4_mask, 7114 }, 7115 { 7116 .type = RTE_FLOW_ITEM_TYPE_UDP, 7117 .spec = &action_vxlan_encap_data->item_udp, 7118 .mask = &rte_flow_item_udp_mask, 7119 }, 7120 { 7121 .type = RTE_FLOW_ITEM_TYPE_VXLAN, 7122 .spec = &action_vxlan_encap_data->item_vxlan, 7123 .mask = &rte_flow_item_vxlan_mask, 7124 }, 7125 { 7126 .type = RTE_FLOW_ITEM_TYPE_END, 7127 }, 7128 }, 7129 .item_eth.type = 0, 7130 .item_vlan = { 7131 .tci = vxlan_encap_conf.vlan_tci, 7132 .inner_type = 0, 7133 }, 7134 .item_ipv4.hdr = { 7135 .src_addr = vxlan_encap_conf.ipv4_src, 7136 .dst_addr = vxlan_encap_conf.ipv4_dst, 7137 }, 7138 .item_udp.hdr = { 7139 .src_port = vxlan_encap_conf.udp_src, 7140 .dst_port = vxlan_encap_conf.udp_dst, 7141 }, 7142 .item_vxlan.flags = 0, 7143 }; 7144 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes, 7145 vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 7146 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes, 7147 vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 7148 if (!vxlan_encap_conf.select_ipv4) { 7149 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr, 7150 &vxlan_encap_conf.ipv6_src, 7151 sizeof(vxlan_encap_conf.ipv6_src)); 7152 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr, 7153 &vxlan_encap_conf.ipv6_dst, 7154 sizeof(vxlan_encap_conf.ipv6_dst)); 7155 action_vxlan_encap_data->items[2] = (struct rte_flow_item){ 7156 .type = RTE_FLOW_ITEM_TYPE_IPV6, 7157 .spec = &action_vxlan_encap_data->item_ipv6, 7158 .mask = &rte_flow_item_ipv6_mask, 7159 }; 7160 } 7161 if (!vxlan_encap_conf.select_vlan) 7162 action_vxlan_encap_data->items[1].type = 7163 RTE_FLOW_ITEM_TYPE_VOID; 7164 if (vxlan_encap_conf.select_tos_ttl) { 7165 if (vxlan_encap_conf.select_ipv4) { 7166 static struct rte_flow_item_ipv4 ipv4_mask_tos; 7167 7168 memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask, 7169 sizeof(ipv4_mask_tos)); 7170 ipv4_mask_tos.hdr.type_of_service = 0xff; 7171 ipv4_mask_tos.hdr.time_to_live = 0xff; 7172 action_vxlan_encap_data->item_ipv4.hdr.type_of_service = 7173 vxlan_encap_conf.ip_tos; 7174 action_vxlan_encap_data->item_ipv4.hdr.time_to_live = 7175 vxlan_encap_conf.ip_ttl; 7176 action_vxlan_encap_data->items[2].mask = 7177 &ipv4_mask_tos; 7178 } else { 7179 static struct rte_flow_item_ipv6 ipv6_mask_tos; 7180 7181 memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask, 7182 sizeof(ipv6_mask_tos)); 7183 ipv6_mask_tos.hdr.vtc_flow |= 7184 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT); 7185 ipv6_mask_tos.hdr.hop_limits = 0xff; 7186 action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |= 7187 rte_cpu_to_be_32 7188 ((uint32_t)vxlan_encap_conf.ip_tos << 7189 RTE_IPV6_HDR_TC_SHIFT); 7190 action_vxlan_encap_data->item_ipv6.hdr.hop_limits = 7191 vxlan_encap_conf.ip_ttl; 7192 action_vxlan_encap_data->items[2].mask = 7193 &ipv6_mask_tos; 7194 } 7195 } 7196 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni, 7197 RTE_DIM(vxlan_encap_conf.vni)); 7198 return 0; 7199 } 7200 7201 /** Parse VXLAN encap action. */ 7202 static int 7203 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token, 7204 const char *str, unsigned int len, 7205 void *buf, unsigned int size) 7206 { 7207 struct buffer *out = buf; 7208 struct rte_flow_action *action; 7209 struct action_vxlan_encap_data *action_vxlan_encap_data; 7210 int ret; 7211 7212 ret = parse_vc(ctx, token, str, len, buf, size); 7213 if (ret < 0) 7214 return ret; 7215 /* Nothing else to do if there is no buffer. */ 7216 if (!out) 7217 return ret; 7218 if (!out->args.vc.actions_n) 7219 return -1; 7220 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 7221 /* Point to selected object. */ 7222 ctx->object = out->args.vc.data; 7223 ctx->objmask = NULL; 7224 action_vxlan_encap_data = ctx->object; 7225 parse_setup_vxlan_encap_data(action_vxlan_encap_data); 7226 action->conf = &action_vxlan_encap_data->conf; 7227 return ret; 7228 } 7229 7230 /** Setup NVGRE encap configuration. */ 7231 static int 7232 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data) 7233 { 7234 /* Set up default configuration. */ 7235 *action_nvgre_encap_data = (struct action_nvgre_encap_data){ 7236 .conf = (struct rte_flow_action_nvgre_encap){ 7237 .definition = action_nvgre_encap_data->items, 7238 }, 7239 .items = { 7240 { 7241 .type = RTE_FLOW_ITEM_TYPE_ETH, 7242 .spec = &action_nvgre_encap_data->item_eth, 7243 .mask = &rte_flow_item_eth_mask, 7244 }, 7245 { 7246 .type = RTE_FLOW_ITEM_TYPE_VLAN, 7247 .spec = &action_nvgre_encap_data->item_vlan, 7248 .mask = &rte_flow_item_vlan_mask, 7249 }, 7250 { 7251 .type = RTE_FLOW_ITEM_TYPE_IPV4, 7252 .spec = &action_nvgre_encap_data->item_ipv4, 7253 .mask = &rte_flow_item_ipv4_mask, 7254 }, 7255 { 7256 .type = RTE_FLOW_ITEM_TYPE_NVGRE, 7257 .spec = &action_nvgre_encap_data->item_nvgre, 7258 .mask = &rte_flow_item_nvgre_mask, 7259 }, 7260 { 7261 .type = RTE_FLOW_ITEM_TYPE_END, 7262 }, 7263 }, 7264 .item_eth.type = 0, 7265 .item_vlan = { 7266 .tci = nvgre_encap_conf.vlan_tci, 7267 .inner_type = 0, 7268 }, 7269 .item_ipv4.hdr = { 7270 .src_addr = nvgre_encap_conf.ipv4_src, 7271 .dst_addr = nvgre_encap_conf.ipv4_dst, 7272 }, 7273 .item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000), 7274 .item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB), 7275 .item_nvgre.flow_id = 0, 7276 }; 7277 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes, 7278 nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 7279 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes, 7280 nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 7281 if (!nvgre_encap_conf.select_ipv4) { 7282 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr, 7283 &nvgre_encap_conf.ipv6_src, 7284 sizeof(nvgre_encap_conf.ipv6_src)); 7285 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr, 7286 &nvgre_encap_conf.ipv6_dst, 7287 sizeof(nvgre_encap_conf.ipv6_dst)); 7288 action_nvgre_encap_data->items[2] = (struct rte_flow_item){ 7289 .type = RTE_FLOW_ITEM_TYPE_IPV6, 7290 .spec = &action_nvgre_encap_data->item_ipv6, 7291 .mask = &rte_flow_item_ipv6_mask, 7292 }; 7293 } 7294 if (!nvgre_encap_conf.select_vlan) 7295 action_nvgre_encap_data->items[1].type = 7296 RTE_FLOW_ITEM_TYPE_VOID; 7297 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni, 7298 RTE_DIM(nvgre_encap_conf.tni)); 7299 return 0; 7300 } 7301 7302 /** Parse NVGRE encap action. */ 7303 static int 7304 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token, 7305 const char *str, unsigned int len, 7306 void *buf, unsigned int size) 7307 { 7308 struct buffer *out = buf; 7309 struct rte_flow_action *action; 7310 struct action_nvgre_encap_data *action_nvgre_encap_data; 7311 int ret; 7312 7313 ret = parse_vc(ctx, token, str, len, buf, size); 7314 if (ret < 0) 7315 return ret; 7316 /* Nothing else to do if there is no buffer. */ 7317 if (!out) 7318 return ret; 7319 if (!out->args.vc.actions_n) 7320 return -1; 7321 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 7322 /* Point to selected object. */ 7323 ctx->object = out->args.vc.data; 7324 ctx->objmask = NULL; 7325 action_nvgre_encap_data = ctx->object; 7326 parse_setup_nvgre_encap_data(action_nvgre_encap_data); 7327 action->conf = &action_nvgre_encap_data->conf; 7328 return ret; 7329 } 7330 7331 /** Parse l2 encap action. */ 7332 static int 7333 parse_vc_action_l2_encap(struct context *ctx, const struct token *token, 7334 const char *str, unsigned int len, 7335 void *buf, unsigned int size) 7336 { 7337 struct buffer *out = buf; 7338 struct rte_flow_action *action; 7339 struct action_raw_encap_data *action_encap_data; 7340 struct rte_flow_item_eth eth = { .type = 0, }; 7341 struct rte_flow_item_vlan vlan = { 7342 .tci = mplsoudp_encap_conf.vlan_tci, 7343 .inner_type = 0, 7344 }; 7345 uint8_t *header; 7346 int ret; 7347 7348 ret = parse_vc(ctx, token, str, len, buf, size); 7349 if (ret < 0) 7350 return ret; 7351 /* Nothing else to do if there is no buffer. */ 7352 if (!out) 7353 return ret; 7354 if (!out->args.vc.actions_n) 7355 return -1; 7356 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 7357 /* Point to selected object. */ 7358 ctx->object = out->args.vc.data; 7359 ctx->objmask = NULL; 7360 /* Copy the headers to the buffer. */ 7361 action_encap_data = ctx->object; 7362 *action_encap_data = (struct action_raw_encap_data) { 7363 .conf = (struct rte_flow_action_raw_encap){ 7364 .data = action_encap_data->data, 7365 }, 7366 .data = {}, 7367 }; 7368 header = action_encap_data->data; 7369 if (l2_encap_conf.select_vlan) 7370 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 7371 else if (l2_encap_conf.select_ipv4) 7372 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 7373 else 7374 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 7375 memcpy(eth.dst.addr_bytes, 7376 l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 7377 memcpy(eth.src.addr_bytes, 7378 l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 7379 memcpy(header, ð, sizeof(eth)); 7380 header += sizeof(eth); 7381 if (l2_encap_conf.select_vlan) { 7382 if (l2_encap_conf.select_ipv4) 7383 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 7384 else 7385 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 7386 memcpy(header, &vlan, sizeof(vlan)); 7387 header += sizeof(vlan); 7388 } 7389 action_encap_data->conf.size = header - 7390 action_encap_data->data; 7391 action->conf = &action_encap_data->conf; 7392 return ret; 7393 } 7394 7395 /** Parse l2 decap action. */ 7396 static int 7397 parse_vc_action_l2_decap(struct context *ctx, const struct token *token, 7398 const char *str, unsigned int len, 7399 void *buf, unsigned int size) 7400 { 7401 struct buffer *out = buf; 7402 struct rte_flow_action *action; 7403 struct action_raw_decap_data *action_decap_data; 7404 struct rte_flow_item_eth eth = { .type = 0, }; 7405 struct rte_flow_item_vlan vlan = { 7406 .tci = mplsoudp_encap_conf.vlan_tci, 7407 .inner_type = 0, 7408 }; 7409 uint8_t *header; 7410 int ret; 7411 7412 ret = parse_vc(ctx, token, str, len, buf, size); 7413 if (ret < 0) 7414 return ret; 7415 /* Nothing else to do if there is no buffer. */ 7416 if (!out) 7417 return ret; 7418 if (!out->args.vc.actions_n) 7419 return -1; 7420 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 7421 /* Point to selected object. */ 7422 ctx->object = out->args.vc.data; 7423 ctx->objmask = NULL; 7424 /* Copy the headers to the buffer. */ 7425 action_decap_data = ctx->object; 7426 *action_decap_data = (struct action_raw_decap_data) { 7427 .conf = (struct rte_flow_action_raw_decap){ 7428 .data = action_decap_data->data, 7429 }, 7430 .data = {}, 7431 }; 7432 header = action_decap_data->data; 7433 if (l2_decap_conf.select_vlan) 7434 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 7435 memcpy(header, ð, sizeof(eth)); 7436 header += sizeof(eth); 7437 if (l2_decap_conf.select_vlan) { 7438 memcpy(header, &vlan, sizeof(vlan)); 7439 header += sizeof(vlan); 7440 } 7441 action_decap_data->conf.size = header - 7442 action_decap_data->data; 7443 action->conf = &action_decap_data->conf; 7444 return ret; 7445 } 7446 7447 #define ETHER_TYPE_MPLS_UNICAST 0x8847 7448 7449 /** Parse MPLSOGRE encap action. */ 7450 static int 7451 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token, 7452 const char *str, unsigned int len, 7453 void *buf, unsigned int size) 7454 { 7455 struct buffer *out = buf; 7456 struct rte_flow_action *action; 7457 struct action_raw_encap_data *action_encap_data; 7458 struct rte_flow_item_eth eth = { .type = 0, }; 7459 struct rte_flow_item_vlan vlan = { 7460 .tci = mplsogre_encap_conf.vlan_tci, 7461 .inner_type = 0, 7462 }; 7463 struct rte_flow_item_ipv4 ipv4 = { 7464 .hdr = { 7465 .src_addr = mplsogre_encap_conf.ipv4_src, 7466 .dst_addr = mplsogre_encap_conf.ipv4_dst, 7467 .next_proto_id = IPPROTO_GRE, 7468 .version_ihl = RTE_IPV4_VHL_DEF, 7469 .time_to_live = IPDEFTTL, 7470 }, 7471 }; 7472 struct rte_flow_item_ipv6 ipv6 = { 7473 .hdr = { 7474 .proto = IPPROTO_GRE, 7475 .hop_limits = IPDEFTTL, 7476 }, 7477 }; 7478 struct rte_flow_item_gre gre = { 7479 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST), 7480 }; 7481 struct rte_flow_item_mpls mpls = { 7482 .ttl = 0, 7483 }; 7484 uint8_t *header; 7485 int ret; 7486 7487 ret = parse_vc(ctx, token, str, len, buf, size); 7488 if (ret < 0) 7489 return ret; 7490 /* Nothing else to do if there is no buffer. */ 7491 if (!out) 7492 return ret; 7493 if (!out->args.vc.actions_n) 7494 return -1; 7495 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 7496 /* Point to selected object. */ 7497 ctx->object = out->args.vc.data; 7498 ctx->objmask = NULL; 7499 /* Copy the headers to the buffer. */ 7500 action_encap_data = ctx->object; 7501 *action_encap_data = (struct action_raw_encap_data) { 7502 .conf = (struct rte_flow_action_raw_encap){ 7503 .data = action_encap_data->data, 7504 }, 7505 .data = {}, 7506 .preserve = {}, 7507 }; 7508 header = action_encap_data->data; 7509 if (mplsogre_encap_conf.select_vlan) 7510 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 7511 else if (mplsogre_encap_conf.select_ipv4) 7512 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 7513 else 7514 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 7515 memcpy(eth.dst.addr_bytes, 7516 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 7517 memcpy(eth.src.addr_bytes, 7518 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 7519 memcpy(header, ð, sizeof(eth)); 7520 header += sizeof(eth); 7521 if (mplsogre_encap_conf.select_vlan) { 7522 if (mplsogre_encap_conf.select_ipv4) 7523 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 7524 else 7525 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 7526 memcpy(header, &vlan, sizeof(vlan)); 7527 header += sizeof(vlan); 7528 } 7529 if (mplsogre_encap_conf.select_ipv4) { 7530 memcpy(header, &ipv4, sizeof(ipv4)); 7531 header += sizeof(ipv4); 7532 } else { 7533 memcpy(&ipv6.hdr.src_addr, 7534 &mplsogre_encap_conf.ipv6_src, 7535 sizeof(mplsogre_encap_conf.ipv6_src)); 7536 memcpy(&ipv6.hdr.dst_addr, 7537 &mplsogre_encap_conf.ipv6_dst, 7538 sizeof(mplsogre_encap_conf.ipv6_dst)); 7539 memcpy(header, &ipv6, sizeof(ipv6)); 7540 header += sizeof(ipv6); 7541 } 7542 memcpy(header, &gre, sizeof(gre)); 7543 header += sizeof(gre); 7544 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label, 7545 RTE_DIM(mplsogre_encap_conf.label)); 7546 mpls.label_tc_s[2] |= 0x1; 7547 memcpy(header, &mpls, sizeof(mpls)); 7548 header += sizeof(mpls); 7549 action_encap_data->conf.size = header - 7550 action_encap_data->data; 7551 action->conf = &action_encap_data->conf; 7552 return ret; 7553 } 7554 7555 /** Parse MPLSOGRE decap action. */ 7556 static int 7557 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token, 7558 const char *str, unsigned int len, 7559 void *buf, unsigned int size) 7560 { 7561 struct buffer *out = buf; 7562 struct rte_flow_action *action; 7563 struct action_raw_decap_data *action_decap_data; 7564 struct rte_flow_item_eth eth = { .type = 0, }; 7565 struct rte_flow_item_vlan vlan = {.tci = 0}; 7566 struct rte_flow_item_ipv4 ipv4 = { 7567 .hdr = { 7568 .next_proto_id = IPPROTO_GRE, 7569 }, 7570 }; 7571 struct rte_flow_item_ipv6 ipv6 = { 7572 .hdr = { 7573 .proto = IPPROTO_GRE, 7574 }, 7575 }; 7576 struct rte_flow_item_gre gre = { 7577 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST), 7578 }; 7579 struct rte_flow_item_mpls mpls; 7580 uint8_t *header; 7581 int ret; 7582 7583 ret = parse_vc(ctx, token, str, len, buf, size); 7584 if (ret < 0) 7585 return ret; 7586 /* Nothing else to do if there is no buffer. */ 7587 if (!out) 7588 return ret; 7589 if (!out->args.vc.actions_n) 7590 return -1; 7591 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 7592 /* Point to selected object. */ 7593 ctx->object = out->args.vc.data; 7594 ctx->objmask = NULL; 7595 /* Copy the headers to the buffer. */ 7596 action_decap_data = ctx->object; 7597 *action_decap_data = (struct action_raw_decap_data) { 7598 .conf = (struct rte_flow_action_raw_decap){ 7599 .data = action_decap_data->data, 7600 }, 7601 .data = {}, 7602 }; 7603 header = action_decap_data->data; 7604 if (mplsogre_decap_conf.select_vlan) 7605 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 7606 else if (mplsogre_encap_conf.select_ipv4) 7607 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 7608 else 7609 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 7610 memcpy(eth.dst.addr_bytes, 7611 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 7612 memcpy(eth.src.addr_bytes, 7613 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 7614 memcpy(header, ð, sizeof(eth)); 7615 header += sizeof(eth); 7616 if (mplsogre_encap_conf.select_vlan) { 7617 if (mplsogre_encap_conf.select_ipv4) 7618 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 7619 else 7620 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 7621 memcpy(header, &vlan, sizeof(vlan)); 7622 header += sizeof(vlan); 7623 } 7624 if (mplsogre_encap_conf.select_ipv4) { 7625 memcpy(header, &ipv4, sizeof(ipv4)); 7626 header += sizeof(ipv4); 7627 } else { 7628 memcpy(header, &ipv6, sizeof(ipv6)); 7629 header += sizeof(ipv6); 7630 } 7631 memcpy(header, &gre, sizeof(gre)); 7632 header += sizeof(gre); 7633 memset(&mpls, 0, sizeof(mpls)); 7634 memcpy(header, &mpls, sizeof(mpls)); 7635 header += sizeof(mpls); 7636 action_decap_data->conf.size = header - 7637 action_decap_data->data; 7638 action->conf = &action_decap_data->conf; 7639 return ret; 7640 } 7641 7642 /** Parse MPLSOUDP encap action. */ 7643 static int 7644 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token, 7645 const char *str, unsigned int len, 7646 void *buf, unsigned int size) 7647 { 7648 struct buffer *out = buf; 7649 struct rte_flow_action *action; 7650 struct action_raw_encap_data *action_encap_data; 7651 struct rte_flow_item_eth eth = { .type = 0, }; 7652 struct rte_flow_item_vlan vlan = { 7653 .tci = mplsoudp_encap_conf.vlan_tci, 7654 .inner_type = 0, 7655 }; 7656 struct rte_flow_item_ipv4 ipv4 = { 7657 .hdr = { 7658 .src_addr = mplsoudp_encap_conf.ipv4_src, 7659 .dst_addr = mplsoudp_encap_conf.ipv4_dst, 7660 .next_proto_id = IPPROTO_UDP, 7661 .version_ihl = RTE_IPV4_VHL_DEF, 7662 .time_to_live = IPDEFTTL, 7663 }, 7664 }; 7665 struct rte_flow_item_ipv6 ipv6 = { 7666 .hdr = { 7667 .proto = IPPROTO_UDP, 7668 .hop_limits = IPDEFTTL, 7669 }, 7670 }; 7671 struct rte_flow_item_udp udp = { 7672 .hdr = { 7673 .src_port = mplsoudp_encap_conf.udp_src, 7674 .dst_port = mplsoudp_encap_conf.udp_dst, 7675 }, 7676 }; 7677 struct rte_flow_item_mpls mpls; 7678 uint8_t *header; 7679 int ret; 7680 7681 ret = parse_vc(ctx, token, str, len, buf, size); 7682 if (ret < 0) 7683 return ret; 7684 /* Nothing else to do if there is no buffer. */ 7685 if (!out) 7686 return ret; 7687 if (!out->args.vc.actions_n) 7688 return -1; 7689 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 7690 /* Point to selected object. */ 7691 ctx->object = out->args.vc.data; 7692 ctx->objmask = NULL; 7693 /* Copy the headers to the buffer. */ 7694 action_encap_data = ctx->object; 7695 *action_encap_data = (struct action_raw_encap_data) { 7696 .conf = (struct rte_flow_action_raw_encap){ 7697 .data = action_encap_data->data, 7698 }, 7699 .data = {}, 7700 .preserve = {}, 7701 }; 7702 header = action_encap_data->data; 7703 if (mplsoudp_encap_conf.select_vlan) 7704 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 7705 else if (mplsoudp_encap_conf.select_ipv4) 7706 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 7707 else 7708 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 7709 memcpy(eth.dst.addr_bytes, 7710 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 7711 memcpy(eth.src.addr_bytes, 7712 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 7713 memcpy(header, ð, sizeof(eth)); 7714 header += sizeof(eth); 7715 if (mplsoudp_encap_conf.select_vlan) { 7716 if (mplsoudp_encap_conf.select_ipv4) 7717 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 7718 else 7719 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 7720 memcpy(header, &vlan, sizeof(vlan)); 7721 header += sizeof(vlan); 7722 } 7723 if (mplsoudp_encap_conf.select_ipv4) { 7724 memcpy(header, &ipv4, sizeof(ipv4)); 7725 header += sizeof(ipv4); 7726 } else { 7727 memcpy(&ipv6.hdr.src_addr, 7728 &mplsoudp_encap_conf.ipv6_src, 7729 sizeof(mplsoudp_encap_conf.ipv6_src)); 7730 memcpy(&ipv6.hdr.dst_addr, 7731 &mplsoudp_encap_conf.ipv6_dst, 7732 sizeof(mplsoudp_encap_conf.ipv6_dst)); 7733 memcpy(header, &ipv6, sizeof(ipv6)); 7734 header += sizeof(ipv6); 7735 } 7736 memcpy(header, &udp, sizeof(udp)); 7737 header += sizeof(udp); 7738 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label, 7739 RTE_DIM(mplsoudp_encap_conf.label)); 7740 mpls.label_tc_s[2] |= 0x1; 7741 memcpy(header, &mpls, sizeof(mpls)); 7742 header += sizeof(mpls); 7743 action_encap_data->conf.size = header - 7744 action_encap_data->data; 7745 action->conf = &action_encap_data->conf; 7746 return ret; 7747 } 7748 7749 /** Parse MPLSOUDP decap action. */ 7750 static int 7751 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token, 7752 const char *str, unsigned int len, 7753 void *buf, unsigned int size) 7754 { 7755 struct buffer *out = buf; 7756 struct rte_flow_action *action; 7757 struct action_raw_decap_data *action_decap_data; 7758 struct rte_flow_item_eth eth = { .type = 0, }; 7759 struct rte_flow_item_vlan vlan = {.tci = 0}; 7760 struct rte_flow_item_ipv4 ipv4 = { 7761 .hdr = { 7762 .next_proto_id = IPPROTO_UDP, 7763 }, 7764 }; 7765 struct rte_flow_item_ipv6 ipv6 = { 7766 .hdr = { 7767 .proto = IPPROTO_UDP, 7768 }, 7769 }; 7770 struct rte_flow_item_udp udp = { 7771 .hdr = { 7772 .dst_port = rte_cpu_to_be_16(6635), 7773 }, 7774 }; 7775 struct rte_flow_item_mpls mpls; 7776 uint8_t *header; 7777 int ret; 7778 7779 ret = parse_vc(ctx, token, str, len, buf, size); 7780 if (ret < 0) 7781 return ret; 7782 /* Nothing else to do if there is no buffer. */ 7783 if (!out) 7784 return ret; 7785 if (!out->args.vc.actions_n) 7786 return -1; 7787 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 7788 /* Point to selected object. */ 7789 ctx->object = out->args.vc.data; 7790 ctx->objmask = NULL; 7791 /* Copy the headers to the buffer. */ 7792 action_decap_data = ctx->object; 7793 *action_decap_data = (struct action_raw_decap_data) { 7794 .conf = (struct rte_flow_action_raw_decap){ 7795 .data = action_decap_data->data, 7796 }, 7797 .data = {}, 7798 }; 7799 header = action_decap_data->data; 7800 if (mplsoudp_decap_conf.select_vlan) 7801 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 7802 else if (mplsoudp_encap_conf.select_ipv4) 7803 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 7804 else 7805 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 7806 memcpy(eth.dst.addr_bytes, 7807 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 7808 memcpy(eth.src.addr_bytes, 7809 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 7810 memcpy(header, ð, sizeof(eth)); 7811 header += sizeof(eth); 7812 if (mplsoudp_encap_conf.select_vlan) { 7813 if (mplsoudp_encap_conf.select_ipv4) 7814 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 7815 else 7816 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 7817 memcpy(header, &vlan, sizeof(vlan)); 7818 header += sizeof(vlan); 7819 } 7820 if (mplsoudp_encap_conf.select_ipv4) { 7821 memcpy(header, &ipv4, sizeof(ipv4)); 7822 header += sizeof(ipv4); 7823 } else { 7824 memcpy(header, &ipv6, sizeof(ipv6)); 7825 header += sizeof(ipv6); 7826 } 7827 memcpy(header, &udp, sizeof(udp)); 7828 header += sizeof(udp); 7829 memset(&mpls, 0, sizeof(mpls)); 7830 memcpy(header, &mpls, sizeof(mpls)); 7831 header += sizeof(mpls); 7832 action_decap_data->conf.size = header - 7833 action_decap_data->data; 7834 action->conf = &action_decap_data->conf; 7835 return ret; 7836 } 7837 7838 static int 7839 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token, 7840 const char *str, unsigned int len, void *buf, 7841 unsigned int size) 7842 { 7843 struct action_raw_decap_data *action_raw_decap_data; 7844 struct rte_flow_action *action; 7845 const struct arg *arg; 7846 struct buffer *out = buf; 7847 int ret; 7848 uint16_t idx; 7849 7850 RTE_SET_USED(token); 7851 RTE_SET_USED(buf); 7852 RTE_SET_USED(size); 7853 arg = ARGS_ENTRY_ARB_BOUNDED 7854 (offsetof(struct action_raw_decap_data, idx), 7855 sizeof(((struct action_raw_decap_data *)0)->idx), 7856 0, RAW_ENCAP_CONFS_MAX_NUM - 1); 7857 if (push_args(ctx, arg)) 7858 return -1; 7859 ret = parse_int(ctx, token, str, len, NULL, 0); 7860 if (ret < 0) { 7861 pop_args(ctx); 7862 return -1; 7863 } 7864 if (!ctx->object) 7865 return len; 7866 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 7867 action_raw_decap_data = ctx->object; 7868 idx = action_raw_decap_data->idx; 7869 action_raw_decap_data->conf.data = raw_decap_confs[idx].data; 7870 action_raw_decap_data->conf.size = raw_decap_confs[idx].size; 7871 action->conf = &action_raw_decap_data->conf; 7872 return len; 7873 } 7874 7875 7876 static int 7877 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token, 7878 const char *str, unsigned int len, void *buf, 7879 unsigned int size) 7880 { 7881 struct action_raw_encap_data *action_raw_encap_data; 7882 struct rte_flow_action *action; 7883 const struct arg *arg; 7884 struct buffer *out = buf; 7885 int ret; 7886 uint16_t idx; 7887 7888 RTE_SET_USED(token); 7889 RTE_SET_USED(buf); 7890 RTE_SET_USED(size); 7891 if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE) 7892 return -1; 7893 arg = ARGS_ENTRY_ARB_BOUNDED 7894 (offsetof(struct action_raw_encap_data, idx), 7895 sizeof(((struct action_raw_encap_data *)0)->idx), 7896 0, RAW_ENCAP_CONFS_MAX_NUM - 1); 7897 if (push_args(ctx, arg)) 7898 return -1; 7899 ret = parse_int(ctx, token, str, len, NULL, 0); 7900 if (ret < 0) { 7901 pop_args(ctx); 7902 return -1; 7903 } 7904 if (!ctx->object) 7905 return len; 7906 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 7907 action_raw_encap_data = ctx->object; 7908 idx = action_raw_encap_data->idx; 7909 action_raw_encap_data->conf.data = raw_encap_confs[idx].data; 7910 action_raw_encap_data->conf.size = raw_encap_confs[idx].size; 7911 action_raw_encap_data->conf.preserve = NULL; 7912 action->conf = &action_raw_encap_data->conf; 7913 return len; 7914 } 7915 7916 static int 7917 parse_vc_action_raw_encap(struct context *ctx, const struct token *token, 7918 const char *str, unsigned int len, void *buf, 7919 unsigned int size) 7920 { 7921 struct buffer *out = buf; 7922 struct rte_flow_action *action; 7923 struct action_raw_encap_data *action_raw_encap_data = NULL; 7924 int ret; 7925 7926 ret = parse_vc(ctx, token, str, len, buf, size); 7927 if (ret < 0) 7928 return ret; 7929 /* Nothing else to do if there is no buffer. */ 7930 if (!out) 7931 return ret; 7932 if (!out->args.vc.actions_n) 7933 return -1; 7934 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 7935 /* Point to selected object. */ 7936 ctx->object = out->args.vc.data; 7937 ctx->objmask = NULL; 7938 /* Copy the headers to the buffer. */ 7939 action_raw_encap_data = ctx->object; 7940 action_raw_encap_data->conf.data = raw_encap_confs[0].data; 7941 action_raw_encap_data->conf.preserve = NULL; 7942 action_raw_encap_data->conf.size = raw_encap_confs[0].size; 7943 action->conf = &action_raw_encap_data->conf; 7944 return ret; 7945 } 7946 7947 static int 7948 parse_vc_action_raw_decap(struct context *ctx, const struct token *token, 7949 const char *str, unsigned int len, void *buf, 7950 unsigned int size) 7951 { 7952 struct buffer *out = buf; 7953 struct rte_flow_action *action; 7954 struct action_raw_decap_data *action_raw_decap_data = NULL; 7955 int ret; 7956 7957 ret = parse_vc(ctx, token, str, len, buf, size); 7958 if (ret < 0) 7959 return ret; 7960 /* Nothing else to do if there is no buffer. */ 7961 if (!out) 7962 return ret; 7963 if (!out->args.vc.actions_n) 7964 return -1; 7965 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 7966 /* Point to selected object. */ 7967 ctx->object = out->args.vc.data; 7968 ctx->objmask = NULL; 7969 /* Copy the headers to the buffer. */ 7970 action_raw_decap_data = ctx->object; 7971 action_raw_decap_data->conf.data = raw_decap_confs[0].data; 7972 action_raw_decap_data->conf.size = raw_decap_confs[0].size; 7973 action->conf = &action_raw_decap_data->conf; 7974 return ret; 7975 } 7976 7977 static int 7978 parse_vc_action_set_meta(struct context *ctx, const struct token *token, 7979 const char *str, unsigned int len, void *buf, 7980 unsigned int size) 7981 { 7982 int ret; 7983 7984 ret = parse_vc(ctx, token, str, len, buf, size); 7985 if (ret < 0) 7986 return ret; 7987 ret = rte_flow_dynf_metadata_register(); 7988 if (ret < 0) 7989 return -1; 7990 return len; 7991 } 7992 7993 static int 7994 parse_vc_action_sample(struct context *ctx, const struct token *token, 7995 const char *str, unsigned int len, void *buf, 7996 unsigned int size) 7997 { 7998 struct buffer *out = buf; 7999 struct rte_flow_action *action; 8000 struct action_sample_data *action_sample_data = NULL; 8001 static struct rte_flow_action end_action = { 8002 RTE_FLOW_ACTION_TYPE_END, 0 8003 }; 8004 int ret; 8005 8006 ret = parse_vc(ctx, token, str, len, buf, size); 8007 if (ret < 0) 8008 return ret; 8009 /* Nothing else to do if there is no buffer. */ 8010 if (!out) 8011 return ret; 8012 if (!out->args.vc.actions_n) 8013 return -1; 8014 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 8015 /* Point to selected object. */ 8016 ctx->object = out->args.vc.data; 8017 ctx->objmask = NULL; 8018 /* Copy the headers to the buffer. */ 8019 action_sample_data = ctx->object; 8020 action_sample_data->conf.actions = &end_action; 8021 action->conf = &action_sample_data->conf; 8022 return ret; 8023 } 8024 8025 static int 8026 parse_vc_action_sample_index(struct context *ctx, const struct token *token, 8027 const char *str, unsigned int len, void *buf, 8028 unsigned int size) 8029 { 8030 struct action_sample_data *action_sample_data; 8031 struct rte_flow_action *action; 8032 const struct arg *arg; 8033 struct buffer *out = buf; 8034 int ret; 8035 uint16_t idx; 8036 8037 RTE_SET_USED(token); 8038 RTE_SET_USED(buf); 8039 RTE_SET_USED(size); 8040 if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE) 8041 return -1; 8042 arg = ARGS_ENTRY_ARB_BOUNDED 8043 (offsetof(struct action_sample_data, idx), 8044 sizeof(((struct action_sample_data *)0)->idx), 8045 0, RAW_SAMPLE_CONFS_MAX_NUM - 1); 8046 if (push_args(ctx, arg)) 8047 return -1; 8048 ret = parse_int(ctx, token, str, len, NULL, 0); 8049 if (ret < 0) { 8050 pop_args(ctx); 8051 return -1; 8052 } 8053 if (!ctx->object) 8054 return len; 8055 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 8056 action_sample_data = ctx->object; 8057 idx = action_sample_data->idx; 8058 action_sample_data->conf.actions = raw_sample_confs[idx].data; 8059 action->conf = &action_sample_data->conf; 8060 return len; 8061 } 8062 8063 /** Parse operation for modify_field command. */ 8064 static int 8065 parse_vc_modify_field_op(struct context *ctx, const struct token *token, 8066 const char *str, unsigned int len, void *buf, 8067 unsigned int size) 8068 { 8069 struct rte_flow_action_modify_field *action_modify_field; 8070 unsigned int i; 8071 8072 (void)token; 8073 (void)buf; 8074 (void)size; 8075 if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE) 8076 return -1; 8077 for (i = 0; modify_field_ops[i]; ++i) 8078 if (!strcmp_partial(modify_field_ops[i], str, len)) 8079 break; 8080 if (!modify_field_ops[i]) 8081 return -1; 8082 if (!ctx->object) 8083 return len; 8084 action_modify_field = ctx->object; 8085 action_modify_field->operation = (enum rte_flow_modify_op)i; 8086 return len; 8087 } 8088 8089 /** Parse id for modify_field command. */ 8090 static int 8091 parse_vc_modify_field_id(struct context *ctx, const struct token *token, 8092 const char *str, unsigned int len, void *buf, 8093 unsigned int size) 8094 { 8095 struct rte_flow_action_modify_field *action_modify_field; 8096 unsigned int i; 8097 8098 (void)token; 8099 (void)buf; 8100 (void)size; 8101 if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE && 8102 ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE) 8103 return -1; 8104 for (i = 0; modify_field_ids[i]; ++i) 8105 if (!strcmp_partial(modify_field_ids[i], str, len)) 8106 break; 8107 if (!modify_field_ids[i]) 8108 return -1; 8109 if (!ctx->object) 8110 return len; 8111 action_modify_field = ctx->object; 8112 if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE) 8113 action_modify_field->dst.field = (enum rte_flow_field_id)i; 8114 else 8115 action_modify_field->src.field = (enum rte_flow_field_id)i; 8116 return len; 8117 } 8118 8119 /** Parse the conntrack update, not a rte_flow_action. */ 8120 static int 8121 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token, 8122 const char *str, unsigned int len, void *buf, 8123 unsigned int size) 8124 { 8125 struct buffer *out = buf; 8126 struct rte_flow_modify_conntrack *ct_modify = NULL; 8127 8128 (void)size; 8129 if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX && 8130 ctx->curr != ACTION_CONNTRACK_UPDATE_DIR) 8131 return -1; 8132 /* Token name must match. */ 8133 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8134 return -1; 8135 /* Nothing else to do if there is no buffer. */ 8136 if (!out) 8137 return len; 8138 ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data; 8139 if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) { 8140 ct_modify->new_ct.is_original_dir = 8141 conntrack_context.is_original_dir; 8142 ct_modify->direction = 1; 8143 } else { 8144 uint32_t old_dir; 8145 8146 old_dir = ct_modify->new_ct.is_original_dir; 8147 memcpy(&ct_modify->new_ct, &conntrack_context, 8148 sizeof(conntrack_context)); 8149 ct_modify->new_ct.is_original_dir = old_dir; 8150 ct_modify->state = 1; 8151 } 8152 return len; 8153 } 8154 8155 /** Parse tokens for destroy command. */ 8156 static int 8157 parse_destroy(struct context *ctx, const struct token *token, 8158 const char *str, unsigned int len, 8159 void *buf, unsigned int size) 8160 { 8161 struct buffer *out = buf; 8162 8163 /* Token name must match. */ 8164 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8165 return -1; 8166 /* Nothing else to do if there is no buffer. */ 8167 if (!out) 8168 return len; 8169 if (!out->command) { 8170 if (ctx->curr != DESTROY) 8171 return -1; 8172 if (sizeof(*out) > size) 8173 return -1; 8174 out->command = ctx->curr; 8175 ctx->objdata = 0; 8176 ctx->object = out; 8177 ctx->objmask = NULL; 8178 out->args.destroy.rule = 8179 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 8180 sizeof(double)); 8181 return len; 8182 } 8183 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) + 8184 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size) 8185 return -1; 8186 ctx->objdata = 0; 8187 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++; 8188 ctx->objmask = NULL; 8189 return len; 8190 } 8191 8192 /** Parse tokens for flush command. */ 8193 static int 8194 parse_flush(struct context *ctx, const struct token *token, 8195 const char *str, unsigned int len, 8196 void *buf, unsigned int size) 8197 { 8198 struct buffer *out = buf; 8199 8200 /* Token name must match. */ 8201 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8202 return -1; 8203 /* Nothing else to do if there is no buffer. */ 8204 if (!out) 8205 return len; 8206 if (!out->command) { 8207 if (ctx->curr != FLUSH) 8208 return -1; 8209 if (sizeof(*out) > size) 8210 return -1; 8211 out->command = ctx->curr; 8212 ctx->objdata = 0; 8213 ctx->object = out; 8214 ctx->objmask = NULL; 8215 } 8216 return len; 8217 } 8218 8219 /** Parse tokens for dump command. */ 8220 static int 8221 parse_dump(struct context *ctx, const struct token *token, 8222 const char *str, unsigned int len, 8223 void *buf, unsigned int size) 8224 { 8225 struct buffer *out = buf; 8226 8227 /* Token name must match. */ 8228 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8229 return -1; 8230 /* Nothing else to do if there is no buffer. */ 8231 if (!out) 8232 return len; 8233 if (!out->command) { 8234 if (ctx->curr != DUMP) 8235 return -1; 8236 if (sizeof(*out) > size) 8237 return -1; 8238 out->command = ctx->curr; 8239 ctx->objdata = 0; 8240 ctx->object = out; 8241 ctx->objmask = NULL; 8242 return len; 8243 } 8244 switch (ctx->curr) { 8245 case DUMP_ALL: 8246 case DUMP_ONE: 8247 out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false; 8248 out->command = ctx->curr; 8249 ctx->objdata = 0; 8250 ctx->object = out; 8251 ctx->objmask = NULL; 8252 return len; 8253 default: 8254 return -1; 8255 } 8256 } 8257 8258 /** Parse tokens for query command. */ 8259 static int 8260 parse_query(struct context *ctx, const struct token *token, 8261 const char *str, unsigned int len, 8262 void *buf, unsigned int size) 8263 { 8264 struct buffer *out = buf; 8265 8266 /* Token name must match. */ 8267 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8268 return -1; 8269 /* Nothing else to do if there is no buffer. */ 8270 if (!out) 8271 return len; 8272 if (!out->command) { 8273 if (ctx->curr != QUERY) 8274 return -1; 8275 if (sizeof(*out) > size) 8276 return -1; 8277 out->command = ctx->curr; 8278 ctx->objdata = 0; 8279 ctx->object = out; 8280 ctx->objmask = NULL; 8281 } 8282 return len; 8283 } 8284 8285 /** Parse action names. */ 8286 static int 8287 parse_action(struct context *ctx, const struct token *token, 8288 const char *str, unsigned int len, 8289 void *buf, unsigned int size) 8290 { 8291 struct buffer *out = buf; 8292 const struct arg *arg = pop_args(ctx); 8293 unsigned int i; 8294 8295 (void)size; 8296 /* Argument is expected. */ 8297 if (!arg) 8298 return -1; 8299 /* Parse action name. */ 8300 for (i = 0; next_action[i]; ++i) { 8301 const struct parse_action_priv *priv; 8302 8303 token = &token_list[next_action[i]]; 8304 if (strcmp_partial(token->name, str, len)) 8305 continue; 8306 priv = token->priv; 8307 if (!priv) 8308 goto error; 8309 if (out) 8310 memcpy((uint8_t *)ctx->object + arg->offset, 8311 &priv->type, 8312 arg->size); 8313 return len; 8314 } 8315 error: 8316 push_args(ctx, arg); 8317 return -1; 8318 } 8319 8320 /** Parse tokens for list command. */ 8321 static int 8322 parse_list(struct context *ctx, const struct token *token, 8323 const char *str, unsigned int len, 8324 void *buf, unsigned int size) 8325 { 8326 struct buffer *out = buf; 8327 8328 /* Token name must match. */ 8329 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8330 return -1; 8331 /* Nothing else to do if there is no buffer. */ 8332 if (!out) 8333 return len; 8334 if (!out->command) { 8335 if (ctx->curr != LIST) 8336 return -1; 8337 if (sizeof(*out) > size) 8338 return -1; 8339 out->command = ctx->curr; 8340 ctx->objdata = 0; 8341 ctx->object = out; 8342 ctx->objmask = NULL; 8343 out->args.list.group = 8344 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 8345 sizeof(double)); 8346 return len; 8347 } 8348 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) + 8349 sizeof(*out->args.list.group)) > (uint8_t *)out + size) 8350 return -1; 8351 ctx->objdata = 0; 8352 ctx->object = out->args.list.group + out->args.list.group_n++; 8353 ctx->objmask = NULL; 8354 return len; 8355 } 8356 8357 /** Parse tokens for list all aged flows command. */ 8358 static int 8359 parse_aged(struct context *ctx, const struct token *token, 8360 const char *str, unsigned int len, 8361 void *buf, unsigned int size) 8362 { 8363 struct buffer *out = buf; 8364 8365 /* Token name must match. */ 8366 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8367 return -1; 8368 /* Nothing else to do if there is no buffer. */ 8369 if (!out) 8370 return len; 8371 if (!out->command) { 8372 if (ctx->curr != AGED) 8373 return -1; 8374 if (sizeof(*out) > size) 8375 return -1; 8376 out->command = ctx->curr; 8377 ctx->objdata = 0; 8378 ctx->object = out; 8379 ctx->objmask = NULL; 8380 } 8381 if (ctx->curr == AGED_DESTROY) 8382 out->args.aged.destroy = 1; 8383 return len; 8384 } 8385 8386 /** Parse tokens for isolate command. */ 8387 static int 8388 parse_isolate(struct context *ctx, const struct token *token, 8389 const char *str, unsigned int len, 8390 void *buf, unsigned int size) 8391 { 8392 struct buffer *out = buf; 8393 8394 /* Token name must match. */ 8395 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8396 return -1; 8397 /* Nothing else to do if there is no buffer. */ 8398 if (!out) 8399 return len; 8400 if (!out->command) { 8401 if (ctx->curr != ISOLATE) 8402 return -1; 8403 if (sizeof(*out) > size) 8404 return -1; 8405 out->command = ctx->curr; 8406 ctx->objdata = 0; 8407 ctx->object = out; 8408 ctx->objmask = NULL; 8409 } 8410 return len; 8411 } 8412 8413 /** Parse tokens for info/configure command. */ 8414 static int 8415 parse_configure(struct context *ctx, const struct token *token, 8416 const char *str, unsigned int len, 8417 void *buf, unsigned int size) 8418 { 8419 struct buffer *out = buf; 8420 8421 /* Token name must match. */ 8422 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8423 return -1; 8424 /* Nothing else to do if there is no buffer. */ 8425 if (!out) 8426 return len; 8427 if (!out->command) { 8428 if (ctx->curr != INFO && ctx->curr != CONFIGURE) 8429 return -1; 8430 if (sizeof(*out) > size) 8431 return -1; 8432 out->command = ctx->curr; 8433 ctx->objdata = 0; 8434 ctx->object = out; 8435 ctx->objmask = NULL; 8436 } 8437 return len; 8438 } 8439 8440 /** Parse tokens for template create command. */ 8441 static int 8442 parse_template(struct context *ctx, const struct token *token, 8443 const char *str, unsigned int len, 8444 void *buf, unsigned int size) 8445 { 8446 struct buffer *out = buf; 8447 8448 /* Token name must match. */ 8449 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8450 return -1; 8451 /* Nothing else to do if there is no buffer. */ 8452 if (!out) 8453 return len; 8454 if (!out->command) { 8455 if (ctx->curr != PATTERN_TEMPLATE && 8456 ctx->curr != ACTIONS_TEMPLATE) 8457 return -1; 8458 if (sizeof(*out) > size) 8459 return -1; 8460 out->command = ctx->curr; 8461 ctx->objdata = 0; 8462 ctx->object = out; 8463 ctx->objmask = NULL; 8464 out->args.vc.data = (uint8_t *)out + size; 8465 return len; 8466 } 8467 switch (ctx->curr) { 8468 case PATTERN_TEMPLATE_CREATE: 8469 out->args.vc.pattern = 8470 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 8471 sizeof(double)); 8472 out->args.vc.pat_templ_id = UINT32_MAX; 8473 out->command = ctx->curr; 8474 ctx->objdata = 0; 8475 ctx->object = out; 8476 ctx->objmask = NULL; 8477 return len; 8478 case PATTERN_TEMPLATE_EGRESS: 8479 out->args.vc.attr.egress = 1; 8480 return len; 8481 case PATTERN_TEMPLATE_INGRESS: 8482 out->args.vc.attr.ingress = 1; 8483 return len; 8484 case PATTERN_TEMPLATE_TRANSFER: 8485 out->args.vc.attr.transfer = 1; 8486 return len; 8487 case ACTIONS_TEMPLATE_CREATE: 8488 out->args.vc.act_templ_id = UINT32_MAX; 8489 out->command = ctx->curr; 8490 ctx->objdata = 0; 8491 ctx->object = out; 8492 ctx->objmask = NULL; 8493 return len; 8494 case ACTIONS_TEMPLATE_SPEC: 8495 out->args.vc.actions = 8496 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 8497 sizeof(double)); 8498 ctx->object = out->args.vc.actions; 8499 ctx->objmask = NULL; 8500 return len; 8501 case ACTIONS_TEMPLATE_MASK: 8502 out->args.vc.masks = 8503 (void *)RTE_ALIGN_CEIL((uintptr_t) 8504 (out->args.vc.actions + 8505 out->args.vc.actions_n), 8506 sizeof(double)); 8507 ctx->object = out->args.vc.masks; 8508 ctx->objmask = NULL; 8509 return len; 8510 case ACTIONS_TEMPLATE_EGRESS: 8511 out->args.vc.attr.egress = 1; 8512 return len; 8513 case ACTIONS_TEMPLATE_INGRESS: 8514 out->args.vc.attr.ingress = 1; 8515 return len; 8516 case ACTIONS_TEMPLATE_TRANSFER: 8517 out->args.vc.attr.transfer = 1; 8518 return len; 8519 default: 8520 return -1; 8521 } 8522 } 8523 8524 /** Parse tokens for template destroy command. */ 8525 static int 8526 parse_template_destroy(struct context *ctx, const struct token *token, 8527 const char *str, unsigned int len, 8528 void *buf, unsigned int size) 8529 { 8530 struct buffer *out = buf; 8531 uint32_t *template_id; 8532 8533 /* Token name must match. */ 8534 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8535 return -1; 8536 /* Nothing else to do if there is no buffer. */ 8537 if (!out) 8538 return len; 8539 if (!out->command || 8540 out->command == PATTERN_TEMPLATE || 8541 out->command == ACTIONS_TEMPLATE) { 8542 if (ctx->curr != PATTERN_TEMPLATE_DESTROY && 8543 ctx->curr != ACTIONS_TEMPLATE_DESTROY) 8544 return -1; 8545 if (sizeof(*out) > size) 8546 return -1; 8547 out->command = ctx->curr; 8548 ctx->objdata = 0; 8549 ctx->object = out; 8550 ctx->objmask = NULL; 8551 out->args.templ_destroy.template_id = 8552 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 8553 sizeof(double)); 8554 return len; 8555 } 8556 template_id = out->args.templ_destroy.template_id 8557 + out->args.templ_destroy.template_id_n++; 8558 if ((uint8_t *)template_id > (uint8_t *)out + size) 8559 return -1; 8560 ctx->objdata = 0; 8561 ctx->object = template_id; 8562 ctx->objmask = NULL; 8563 return len; 8564 } 8565 8566 /** Parse tokens for table create command. */ 8567 static int 8568 parse_table(struct context *ctx, const struct token *token, 8569 const char *str, unsigned int len, 8570 void *buf, unsigned int size) 8571 { 8572 struct buffer *out = buf; 8573 uint32_t *template_id; 8574 8575 /* Token name must match. */ 8576 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8577 return -1; 8578 /* Nothing else to do if there is no buffer. */ 8579 if (!out) 8580 return len; 8581 if (!out->command) { 8582 if (ctx->curr != TABLE) 8583 return -1; 8584 if (sizeof(*out) > size) 8585 return -1; 8586 out->command = ctx->curr; 8587 ctx->objdata = 0; 8588 ctx->object = out; 8589 ctx->objmask = NULL; 8590 return len; 8591 } 8592 switch (ctx->curr) { 8593 case TABLE_CREATE: 8594 out->command = ctx->curr; 8595 ctx->objdata = 0; 8596 ctx->object = out; 8597 ctx->objmask = NULL; 8598 out->args.table.id = UINT32_MAX; 8599 return len; 8600 case TABLE_PATTERN_TEMPLATE: 8601 out->args.table.pat_templ_id = 8602 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 8603 sizeof(double)); 8604 template_id = out->args.table.pat_templ_id 8605 + out->args.table.pat_templ_id_n++; 8606 if ((uint8_t *)template_id > (uint8_t *)out + size) 8607 return -1; 8608 ctx->objdata = 0; 8609 ctx->object = template_id; 8610 ctx->objmask = NULL; 8611 return len; 8612 case TABLE_ACTIONS_TEMPLATE: 8613 out->args.table.act_templ_id = 8614 (void *)RTE_ALIGN_CEIL((uintptr_t) 8615 (out->args.table.pat_templ_id + 8616 out->args.table.pat_templ_id_n), 8617 sizeof(double)); 8618 template_id = out->args.table.act_templ_id 8619 + out->args.table.act_templ_id_n++; 8620 if ((uint8_t *)template_id > (uint8_t *)out + size) 8621 return -1; 8622 ctx->objdata = 0; 8623 ctx->object = template_id; 8624 ctx->objmask = NULL; 8625 return len; 8626 case TABLE_INGRESS: 8627 out->args.table.attr.flow_attr.ingress = 1; 8628 return len; 8629 case TABLE_EGRESS: 8630 out->args.table.attr.flow_attr.egress = 1; 8631 return len; 8632 case TABLE_TRANSFER: 8633 out->args.table.attr.flow_attr.transfer = 1; 8634 return len; 8635 default: 8636 return -1; 8637 } 8638 } 8639 8640 /** Parse tokens for table destroy command. */ 8641 static int 8642 parse_table_destroy(struct context *ctx, const struct token *token, 8643 const char *str, unsigned int len, 8644 void *buf, unsigned int size) 8645 { 8646 struct buffer *out = buf; 8647 uint32_t *table_id; 8648 8649 /* Token name must match. */ 8650 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8651 return -1; 8652 /* Nothing else to do if there is no buffer. */ 8653 if (!out) 8654 return len; 8655 if (!out->command || out->command == TABLE) { 8656 if (ctx->curr != TABLE_DESTROY) 8657 return -1; 8658 if (sizeof(*out) > size) 8659 return -1; 8660 out->command = ctx->curr; 8661 ctx->objdata = 0; 8662 ctx->object = out; 8663 ctx->objmask = NULL; 8664 out->args.table_destroy.table_id = 8665 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 8666 sizeof(double)); 8667 return len; 8668 } 8669 table_id = out->args.table_destroy.table_id 8670 + out->args.table_destroy.table_id_n++; 8671 if ((uint8_t *)table_id > (uint8_t *)out + size) 8672 return -1; 8673 ctx->objdata = 0; 8674 ctx->object = table_id; 8675 ctx->objmask = NULL; 8676 return len; 8677 } 8678 8679 /** Parse tokens for queue create commands. */ 8680 static int 8681 parse_qo(struct context *ctx, const struct token *token, 8682 const char *str, unsigned int len, 8683 void *buf, unsigned int size) 8684 { 8685 struct buffer *out = buf; 8686 8687 /* Token name must match. */ 8688 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8689 return -1; 8690 /* Nothing else to do if there is no buffer. */ 8691 if (!out) 8692 return len; 8693 if (!out->command) { 8694 if (ctx->curr != QUEUE) 8695 return -1; 8696 if (sizeof(*out) > size) 8697 return -1; 8698 out->command = ctx->curr; 8699 ctx->objdata = 0; 8700 ctx->object = out; 8701 ctx->objmask = NULL; 8702 out->args.vc.data = (uint8_t *)out + size; 8703 return len; 8704 } 8705 switch (ctx->curr) { 8706 case QUEUE_CREATE: 8707 out->command = ctx->curr; 8708 ctx->objdata = 0; 8709 ctx->object = out; 8710 ctx->objmask = NULL; 8711 return len; 8712 case QUEUE_TEMPLATE_TABLE: 8713 case QUEUE_PATTERN_TEMPLATE: 8714 case QUEUE_ACTIONS_TEMPLATE: 8715 case QUEUE_CREATE_POSTPONE: 8716 return len; 8717 case ITEM_PATTERN: 8718 out->args.vc.pattern = 8719 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 8720 sizeof(double)); 8721 ctx->object = out->args.vc.pattern; 8722 ctx->objmask = NULL; 8723 return len; 8724 case ACTIONS: 8725 out->args.vc.actions = 8726 (void *)RTE_ALIGN_CEIL((uintptr_t) 8727 (out->args.vc.pattern + 8728 out->args.vc.pattern_n), 8729 sizeof(double)); 8730 ctx->object = out->args.vc.actions; 8731 ctx->objmask = NULL; 8732 return len; 8733 default: 8734 return -1; 8735 } 8736 } 8737 8738 /** Parse tokens for queue destroy command. */ 8739 static int 8740 parse_qo_destroy(struct context *ctx, const struct token *token, 8741 const char *str, unsigned int len, 8742 void *buf, unsigned int size) 8743 { 8744 struct buffer *out = buf; 8745 uint32_t *flow_id; 8746 8747 /* Token name must match. */ 8748 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8749 return -1; 8750 /* Nothing else to do if there is no buffer. */ 8751 if (!out) 8752 return len; 8753 if (!out->command || out->command == QUEUE) { 8754 if (ctx->curr != QUEUE_DESTROY) 8755 return -1; 8756 if (sizeof(*out) > size) 8757 return -1; 8758 out->command = ctx->curr; 8759 ctx->objdata = 0; 8760 ctx->object = out; 8761 ctx->objmask = NULL; 8762 out->args.destroy.rule = 8763 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 8764 sizeof(double)); 8765 return len; 8766 } 8767 switch (ctx->curr) { 8768 case QUEUE_DESTROY_ID: 8769 flow_id = out->args.destroy.rule 8770 + out->args.destroy.rule_n++; 8771 if ((uint8_t *)flow_id > (uint8_t *)out + size) 8772 return -1; 8773 ctx->objdata = 0; 8774 ctx->object = flow_id; 8775 ctx->objmask = NULL; 8776 return len; 8777 case QUEUE_DESTROY_POSTPONE: 8778 return len; 8779 default: 8780 return -1; 8781 } 8782 } 8783 8784 /** Parse tokens for push queue command. */ 8785 static int 8786 parse_push(struct context *ctx, const struct token *token, 8787 const char *str, unsigned int len, 8788 void *buf, unsigned int size) 8789 { 8790 struct buffer *out = buf; 8791 8792 /* Token name must match. */ 8793 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8794 return -1; 8795 /* Nothing else to do if there is no buffer. */ 8796 if (!out) 8797 return len; 8798 if (!out->command) { 8799 if (ctx->curr != PUSH) 8800 return -1; 8801 if (sizeof(*out) > size) 8802 return -1; 8803 out->command = ctx->curr; 8804 ctx->objdata = 0; 8805 ctx->object = out; 8806 ctx->objmask = NULL; 8807 out->args.vc.data = (uint8_t *)out + size; 8808 } 8809 return len; 8810 } 8811 8812 /** Parse tokens for pull command. */ 8813 static int 8814 parse_pull(struct context *ctx, const struct token *token, 8815 const char *str, unsigned int len, 8816 void *buf, unsigned int size) 8817 { 8818 struct buffer *out = buf; 8819 8820 /* Token name must match. */ 8821 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8822 return -1; 8823 /* Nothing else to do if there is no buffer. */ 8824 if (!out) 8825 return len; 8826 if (!out->command) { 8827 if (ctx->curr != PULL) 8828 return -1; 8829 if (sizeof(*out) > size) 8830 return -1; 8831 out->command = ctx->curr; 8832 ctx->objdata = 0; 8833 ctx->object = out; 8834 ctx->objmask = NULL; 8835 out->args.vc.data = (uint8_t *)out + size; 8836 } 8837 return len; 8838 } 8839 8840 static int 8841 parse_flex(struct context *ctx, const struct token *token, 8842 const char *str, unsigned int len, 8843 void *buf, unsigned int size) 8844 { 8845 struct buffer *out = buf; 8846 8847 /* Token name must match. */ 8848 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8849 return -1; 8850 /* Nothing else to do if there is no buffer. */ 8851 if (!out) 8852 return len; 8853 if (out->command == ZERO) { 8854 if (ctx->curr != FLEX) 8855 return -1; 8856 if (sizeof(*out) > size) 8857 return -1; 8858 out->command = ctx->curr; 8859 ctx->objdata = 0; 8860 ctx->object = out; 8861 ctx->objmask = NULL; 8862 } else { 8863 switch (ctx->curr) { 8864 default: 8865 break; 8866 case FLEX_ITEM_INIT: 8867 case FLEX_ITEM_CREATE: 8868 case FLEX_ITEM_DESTROY: 8869 out->command = ctx->curr; 8870 break; 8871 } 8872 } 8873 8874 return len; 8875 } 8876 8877 static int 8878 parse_tunnel(struct context *ctx, const struct token *token, 8879 const char *str, unsigned int len, 8880 void *buf, unsigned int size) 8881 { 8882 struct buffer *out = buf; 8883 8884 /* Token name must match. */ 8885 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8886 return -1; 8887 /* Nothing else to do if there is no buffer. */ 8888 if (!out) 8889 return len; 8890 if (!out->command) { 8891 if (ctx->curr != TUNNEL) 8892 return -1; 8893 if (sizeof(*out) > size) 8894 return -1; 8895 out->command = ctx->curr; 8896 ctx->objdata = 0; 8897 ctx->object = out; 8898 ctx->objmask = NULL; 8899 } else { 8900 switch (ctx->curr) { 8901 default: 8902 break; 8903 case TUNNEL_CREATE: 8904 case TUNNEL_DESTROY: 8905 case TUNNEL_LIST: 8906 out->command = ctx->curr; 8907 break; 8908 case TUNNEL_CREATE_TYPE: 8909 case TUNNEL_DESTROY_ID: 8910 ctx->object = &out->args.vc.tunnel_ops; 8911 break; 8912 } 8913 } 8914 8915 return len; 8916 } 8917 8918 /** 8919 * Parse signed/unsigned integers 8 to 64-bit long. 8920 * 8921 * Last argument (ctx->args) is retrieved to determine integer type and 8922 * storage location. 8923 */ 8924 static int 8925 parse_int(struct context *ctx, const struct token *token, 8926 const char *str, unsigned int len, 8927 void *buf, unsigned int size) 8928 { 8929 const struct arg *arg = pop_args(ctx); 8930 uintmax_t u; 8931 char *end; 8932 8933 (void)token; 8934 /* Argument is expected. */ 8935 if (!arg) 8936 return -1; 8937 errno = 0; 8938 u = arg->sign ? 8939 (uintmax_t)strtoimax(str, &end, 0) : 8940 strtoumax(str, &end, 0); 8941 if (errno || (size_t)(end - str) != len) 8942 goto error; 8943 if (arg->bounded && 8944 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min || 8945 (intmax_t)u > (intmax_t)arg->max)) || 8946 (!arg->sign && (u < arg->min || u > arg->max)))) 8947 goto error; 8948 if (!ctx->object) 8949 return len; 8950 if (arg->mask) { 8951 if (!arg_entry_bf_fill(ctx->object, u, arg) || 8952 !arg_entry_bf_fill(ctx->objmask, -1, arg)) 8953 goto error; 8954 return len; 8955 } 8956 buf = (uint8_t *)ctx->object + arg->offset; 8957 size = arg->size; 8958 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t)) 8959 return -1; 8960 objmask: 8961 switch (size) { 8962 case sizeof(uint8_t): 8963 *(uint8_t *)buf = u; 8964 break; 8965 case sizeof(uint16_t): 8966 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u; 8967 break; 8968 case sizeof(uint8_t [3]): 8969 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 8970 if (!arg->hton) { 8971 ((uint8_t *)buf)[0] = u; 8972 ((uint8_t *)buf)[1] = u >> 8; 8973 ((uint8_t *)buf)[2] = u >> 16; 8974 break; 8975 } 8976 #endif 8977 ((uint8_t *)buf)[0] = u >> 16; 8978 ((uint8_t *)buf)[1] = u >> 8; 8979 ((uint8_t *)buf)[2] = u; 8980 break; 8981 case sizeof(uint32_t): 8982 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u; 8983 break; 8984 case sizeof(uint64_t): 8985 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u; 8986 break; 8987 default: 8988 goto error; 8989 } 8990 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) { 8991 u = -1; 8992 buf = (uint8_t *)ctx->objmask + arg->offset; 8993 goto objmask; 8994 } 8995 return len; 8996 error: 8997 push_args(ctx, arg); 8998 return -1; 8999 } 9000 9001 /** 9002 * Parse a string. 9003 * 9004 * Three arguments (ctx->args) are retrieved from the stack to store data, 9005 * its actual length and address (in that order). 9006 */ 9007 static int 9008 parse_string(struct context *ctx, const struct token *token, 9009 const char *str, unsigned int len, 9010 void *buf, unsigned int size) 9011 { 9012 const struct arg *arg_data = pop_args(ctx); 9013 const struct arg *arg_len = pop_args(ctx); 9014 const struct arg *arg_addr = pop_args(ctx); 9015 char tmp[16]; /* Ought to be enough. */ 9016 int ret; 9017 9018 /* Arguments are expected. */ 9019 if (!arg_data) 9020 return -1; 9021 if (!arg_len) { 9022 push_args(ctx, arg_data); 9023 return -1; 9024 } 9025 if (!arg_addr) { 9026 push_args(ctx, arg_len); 9027 push_args(ctx, arg_data); 9028 return -1; 9029 } 9030 size = arg_data->size; 9031 /* Bit-mask fill is not supported. */ 9032 if (arg_data->mask || size < len) 9033 goto error; 9034 if (!ctx->object) 9035 return len; 9036 /* Let parse_int() fill length information first. */ 9037 ret = snprintf(tmp, sizeof(tmp), "%u", len); 9038 if (ret < 0) 9039 goto error; 9040 push_args(ctx, arg_len); 9041 ret = parse_int(ctx, token, tmp, ret, NULL, 0); 9042 if (ret < 0) { 9043 pop_args(ctx); 9044 goto error; 9045 } 9046 buf = (uint8_t *)ctx->object + arg_data->offset; 9047 /* Output buffer is not necessarily NUL-terminated. */ 9048 memcpy(buf, str, len); 9049 memset((uint8_t *)buf + len, 0x00, size - len); 9050 if (ctx->objmask) 9051 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len); 9052 /* Save address if requested. */ 9053 if (arg_addr->size) { 9054 memcpy((uint8_t *)ctx->object + arg_addr->offset, 9055 (void *[]){ 9056 (uint8_t *)ctx->object + arg_data->offset 9057 }, 9058 arg_addr->size); 9059 if (ctx->objmask) 9060 memcpy((uint8_t *)ctx->objmask + arg_addr->offset, 9061 (void *[]){ 9062 (uint8_t *)ctx->objmask + arg_data->offset 9063 }, 9064 arg_addr->size); 9065 } 9066 return len; 9067 error: 9068 push_args(ctx, arg_addr); 9069 push_args(ctx, arg_len); 9070 push_args(ctx, arg_data); 9071 return -1; 9072 } 9073 9074 static int 9075 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size) 9076 { 9077 const uint8_t *head = dst; 9078 uint32_t left; 9079 9080 /* Check input parameters */ 9081 if ((src == NULL) || 9082 (dst == NULL) || 9083 (size == NULL) || 9084 (*size == 0)) 9085 return -1; 9086 9087 left = *size; 9088 9089 /* Convert chars to bytes */ 9090 while (left) { 9091 char tmp[3], *end = tmp; 9092 uint32_t read_lim = left & 1 ? 1 : 2; 9093 9094 snprintf(tmp, read_lim + 1, "%s", src); 9095 *dst = strtoul(tmp, &end, 16); 9096 if (*end) { 9097 *dst = 0; 9098 *size = (uint32_t)(dst - head); 9099 return -1; 9100 } 9101 left -= read_lim; 9102 src += read_lim; 9103 dst++; 9104 } 9105 *dst = 0; 9106 *size = (uint32_t)(dst - head); 9107 return 0; 9108 } 9109 9110 static int 9111 parse_hex(struct context *ctx, const struct token *token, 9112 const char *str, unsigned int len, 9113 void *buf, unsigned int size) 9114 { 9115 const struct arg *arg_data = pop_args(ctx); 9116 const struct arg *arg_len = pop_args(ctx); 9117 const struct arg *arg_addr = pop_args(ctx); 9118 char tmp[16]; /* Ought to be enough. */ 9119 int ret; 9120 unsigned int hexlen = len; 9121 unsigned int length = 256; 9122 uint8_t hex_tmp[length]; 9123 9124 /* Arguments are expected. */ 9125 if (!arg_data) 9126 return -1; 9127 if (!arg_len) { 9128 push_args(ctx, arg_data); 9129 return -1; 9130 } 9131 if (!arg_addr) { 9132 push_args(ctx, arg_len); 9133 push_args(ctx, arg_data); 9134 return -1; 9135 } 9136 size = arg_data->size; 9137 /* Bit-mask fill is not supported. */ 9138 if (arg_data->mask) 9139 goto error; 9140 if (!ctx->object) 9141 return len; 9142 9143 /* translate bytes string to array. */ 9144 if (str[0] == '0' && ((str[1] == 'x') || 9145 (str[1] == 'X'))) { 9146 str += 2; 9147 hexlen -= 2; 9148 } 9149 if (hexlen > length) 9150 goto error; 9151 ret = parse_hex_string(str, hex_tmp, &hexlen); 9152 if (ret < 0) 9153 goto error; 9154 /* Check the converted binary fits into data buffer. */ 9155 if (hexlen > size) 9156 goto error; 9157 /* Let parse_int() fill length information first. */ 9158 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen); 9159 if (ret < 0) 9160 goto error; 9161 /* Save length if requested. */ 9162 if (arg_len->size) { 9163 push_args(ctx, arg_len); 9164 ret = parse_int(ctx, token, tmp, ret, NULL, 0); 9165 if (ret < 0) { 9166 pop_args(ctx); 9167 goto error; 9168 } 9169 } 9170 buf = (uint8_t *)ctx->object + arg_data->offset; 9171 /* Output buffer is not necessarily NUL-terminated. */ 9172 memcpy(buf, hex_tmp, hexlen); 9173 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen); 9174 if (ctx->objmask) 9175 memset((uint8_t *)ctx->objmask + arg_data->offset, 9176 0xff, hexlen); 9177 /* Save address if requested. */ 9178 if (arg_addr->size) { 9179 memcpy((uint8_t *)ctx->object + arg_addr->offset, 9180 (void *[]){ 9181 (uint8_t *)ctx->object + arg_data->offset 9182 }, 9183 arg_addr->size); 9184 if (ctx->objmask) 9185 memcpy((uint8_t *)ctx->objmask + arg_addr->offset, 9186 (void *[]){ 9187 (uint8_t *)ctx->objmask + arg_data->offset 9188 }, 9189 arg_addr->size); 9190 } 9191 return len; 9192 error: 9193 push_args(ctx, arg_addr); 9194 push_args(ctx, arg_len); 9195 push_args(ctx, arg_data); 9196 return -1; 9197 9198 } 9199 9200 /** 9201 * Parse a zero-ended string. 9202 */ 9203 static int 9204 parse_string0(struct context *ctx, const struct token *token __rte_unused, 9205 const char *str, unsigned int len, 9206 void *buf, unsigned int size) 9207 { 9208 const struct arg *arg_data = pop_args(ctx); 9209 9210 /* Arguments are expected. */ 9211 if (!arg_data) 9212 return -1; 9213 size = arg_data->size; 9214 /* Bit-mask fill is not supported. */ 9215 if (arg_data->mask || size < len + 1) 9216 goto error; 9217 if (!ctx->object) 9218 return len; 9219 buf = (uint8_t *)ctx->object + arg_data->offset; 9220 strncpy(buf, str, len); 9221 if (ctx->objmask) 9222 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len); 9223 return len; 9224 error: 9225 push_args(ctx, arg_data); 9226 return -1; 9227 } 9228 9229 /** 9230 * Parse a MAC address. 9231 * 9232 * Last argument (ctx->args) is retrieved to determine storage size and 9233 * location. 9234 */ 9235 static int 9236 parse_mac_addr(struct context *ctx, const struct token *token, 9237 const char *str, unsigned int len, 9238 void *buf, unsigned int size) 9239 { 9240 const struct arg *arg = pop_args(ctx); 9241 struct rte_ether_addr tmp; 9242 int ret; 9243 9244 (void)token; 9245 /* Argument is expected. */ 9246 if (!arg) 9247 return -1; 9248 size = arg->size; 9249 /* Bit-mask fill is not supported. */ 9250 if (arg->mask || size != sizeof(tmp)) 9251 goto error; 9252 /* Only network endian is supported. */ 9253 if (!arg->hton) 9254 goto error; 9255 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size); 9256 if (ret < 0 || (unsigned int)ret != len) 9257 goto error; 9258 if (!ctx->object) 9259 return len; 9260 buf = (uint8_t *)ctx->object + arg->offset; 9261 memcpy(buf, &tmp, size); 9262 if (ctx->objmask) 9263 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 9264 return len; 9265 error: 9266 push_args(ctx, arg); 9267 return -1; 9268 } 9269 9270 /** 9271 * Parse an IPv4 address. 9272 * 9273 * Last argument (ctx->args) is retrieved to determine storage size and 9274 * location. 9275 */ 9276 static int 9277 parse_ipv4_addr(struct context *ctx, const struct token *token, 9278 const char *str, unsigned int len, 9279 void *buf, unsigned int size) 9280 { 9281 const struct arg *arg = pop_args(ctx); 9282 char str2[len + 1]; 9283 struct in_addr tmp; 9284 int ret; 9285 9286 /* Argument is expected. */ 9287 if (!arg) 9288 return -1; 9289 size = arg->size; 9290 /* Bit-mask fill is not supported. */ 9291 if (arg->mask || size != sizeof(tmp)) 9292 goto error; 9293 /* Only network endian is supported. */ 9294 if (!arg->hton) 9295 goto error; 9296 memcpy(str2, str, len); 9297 str2[len] = '\0'; 9298 ret = inet_pton(AF_INET, str2, &tmp); 9299 if (ret != 1) { 9300 /* Attempt integer parsing. */ 9301 push_args(ctx, arg); 9302 return parse_int(ctx, token, str, len, buf, size); 9303 } 9304 if (!ctx->object) 9305 return len; 9306 buf = (uint8_t *)ctx->object + arg->offset; 9307 memcpy(buf, &tmp, size); 9308 if (ctx->objmask) 9309 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 9310 return len; 9311 error: 9312 push_args(ctx, arg); 9313 return -1; 9314 } 9315 9316 /** 9317 * Parse an IPv6 address. 9318 * 9319 * Last argument (ctx->args) is retrieved to determine storage size and 9320 * location. 9321 */ 9322 static int 9323 parse_ipv6_addr(struct context *ctx, const struct token *token, 9324 const char *str, unsigned int len, 9325 void *buf, unsigned int size) 9326 { 9327 const struct arg *arg = pop_args(ctx); 9328 char str2[len + 1]; 9329 struct in6_addr tmp; 9330 int ret; 9331 9332 (void)token; 9333 /* Argument is expected. */ 9334 if (!arg) 9335 return -1; 9336 size = arg->size; 9337 /* Bit-mask fill is not supported. */ 9338 if (arg->mask || size != sizeof(tmp)) 9339 goto error; 9340 /* Only network endian is supported. */ 9341 if (!arg->hton) 9342 goto error; 9343 memcpy(str2, str, len); 9344 str2[len] = '\0'; 9345 ret = inet_pton(AF_INET6, str2, &tmp); 9346 if (ret != 1) 9347 goto error; 9348 if (!ctx->object) 9349 return len; 9350 buf = (uint8_t *)ctx->object + arg->offset; 9351 memcpy(buf, &tmp, size); 9352 if (ctx->objmask) 9353 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 9354 return len; 9355 error: 9356 push_args(ctx, arg); 9357 return -1; 9358 } 9359 9360 /** Boolean values (even indices stand for false). */ 9361 static const char *const boolean_name[] = { 9362 "0", "1", 9363 "false", "true", 9364 "no", "yes", 9365 "N", "Y", 9366 "off", "on", 9367 NULL, 9368 }; 9369 9370 /** 9371 * Parse a boolean value. 9372 * 9373 * Last argument (ctx->args) is retrieved to determine storage size and 9374 * location. 9375 */ 9376 static int 9377 parse_boolean(struct context *ctx, const struct token *token, 9378 const char *str, unsigned int len, 9379 void *buf, unsigned int size) 9380 { 9381 const struct arg *arg = pop_args(ctx); 9382 unsigned int i; 9383 int ret; 9384 9385 /* Argument is expected. */ 9386 if (!arg) 9387 return -1; 9388 for (i = 0; boolean_name[i]; ++i) 9389 if (!strcmp_partial(boolean_name[i], str, len)) 9390 break; 9391 /* Process token as integer. */ 9392 if (boolean_name[i]) 9393 str = i & 1 ? "1" : "0"; 9394 push_args(ctx, arg); 9395 ret = parse_int(ctx, token, str, strlen(str), buf, size); 9396 return ret > 0 ? (int)len : ret; 9397 } 9398 9399 /** Parse port and update context. */ 9400 static int 9401 parse_port(struct context *ctx, const struct token *token, 9402 const char *str, unsigned int len, 9403 void *buf, unsigned int size) 9404 { 9405 struct buffer *out = &(struct buffer){ .port = 0 }; 9406 int ret; 9407 9408 if (buf) 9409 out = buf; 9410 else { 9411 ctx->objdata = 0; 9412 ctx->object = out; 9413 ctx->objmask = NULL; 9414 size = sizeof(*out); 9415 } 9416 ret = parse_int(ctx, token, str, len, out, size); 9417 if (ret >= 0) 9418 ctx->port = out->port; 9419 if (!buf) 9420 ctx->object = NULL; 9421 return ret; 9422 } 9423 9424 static int 9425 parse_ia_id2ptr(struct context *ctx, const struct token *token, 9426 const char *str, unsigned int len, 9427 void *buf, unsigned int size) 9428 { 9429 struct rte_flow_action *action = ctx->object; 9430 uint32_t id; 9431 int ret; 9432 9433 (void)buf; 9434 (void)size; 9435 ctx->objdata = 0; 9436 ctx->object = &id; 9437 ctx->objmask = NULL; 9438 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id)); 9439 ctx->object = action; 9440 if (ret != (int)len) 9441 return ret; 9442 /* set indirect action */ 9443 if (action) { 9444 action->conf = port_action_handle_get_by_id(ctx->port, id); 9445 ret = (action->conf) ? ret : -1; 9446 } 9447 return ret; 9448 } 9449 9450 /** Parse set command, initialize output buffer for subsequent tokens. */ 9451 static int 9452 parse_set_raw_encap_decap(struct context *ctx, const struct token *token, 9453 const char *str, unsigned int len, 9454 void *buf, unsigned int size) 9455 { 9456 struct buffer *out = buf; 9457 9458 /* Token name must match. */ 9459 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 9460 return -1; 9461 /* Nothing else to do if there is no buffer. */ 9462 if (!out) 9463 return len; 9464 /* Make sure buffer is large enough. */ 9465 if (size < sizeof(*out)) 9466 return -1; 9467 ctx->objdata = 0; 9468 ctx->objmask = NULL; 9469 ctx->object = out; 9470 if (!out->command) 9471 return -1; 9472 out->command = ctx->curr; 9473 /* For encap/decap we need is pattern */ 9474 out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 9475 sizeof(double)); 9476 return len; 9477 } 9478 9479 /** Parse set command, initialize output buffer for subsequent tokens. */ 9480 static int 9481 parse_set_sample_action(struct context *ctx, const struct token *token, 9482 const char *str, unsigned int len, 9483 void *buf, unsigned int size) 9484 { 9485 struct buffer *out = buf; 9486 9487 /* Token name must match. */ 9488 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 9489 return -1; 9490 /* Nothing else to do if there is no buffer. */ 9491 if (!out) 9492 return len; 9493 /* Make sure buffer is large enough. */ 9494 if (size < sizeof(*out)) 9495 return -1; 9496 ctx->objdata = 0; 9497 ctx->objmask = NULL; 9498 ctx->object = out; 9499 if (!out->command) 9500 return -1; 9501 out->command = ctx->curr; 9502 /* For sampler we need is actions */ 9503 out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 9504 sizeof(double)); 9505 return len; 9506 } 9507 9508 /** 9509 * Parse set raw_encap/raw_decap command, 9510 * initialize output buffer for subsequent tokens. 9511 */ 9512 static int 9513 parse_set_init(struct context *ctx, const struct token *token, 9514 const char *str, unsigned int len, 9515 void *buf, unsigned int size) 9516 { 9517 struct buffer *out = buf; 9518 9519 /* Token name must match. */ 9520 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 9521 return -1; 9522 /* Nothing else to do if there is no buffer. */ 9523 if (!out) 9524 return len; 9525 /* Make sure buffer is large enough. */ 9526 if (size < sizeof(*out)) 9527 return -1; 9528 /* Initialize buffer. */ 9529 memset(out, 0x00, sizeof(*out)); 9530 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out)); 9531 ctx->objdata = 0; 9532 ctx->object = out; 9533 ctx->objmask = NULL; 9534 if (!out->command) { 9535 if (ctx->curr != SET) 9536 return -1; 9537 if (sizeof(*out) > size) 9538 return -1; 9539 out->command = ctx->curr; 9540 out->args.vc.data = (uint8_t *)out + size; 9541 ctx->object = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 9542 sizeof(double)); 9543 } 9544 return len; 9545 } 9546 9547 /* 9548 * Replace testpmd handles in a flex flow item with real values. 9549 */ 9550 static int 9551 parse_flex_handle(struct context *ctx, const struct token *token, 9552 const char *str, unsigned int len, 9553 void *buf, unsigned int size) 9554 { 9555 struct rte_flow_item_flex *spec, *mask; 9556 const struct rte_flow_item_flex *src_spec, *src_mask; 9557 const struct arg *arg = pop_args(ctx); 9558 uint32_t offset; 9559 uint16_t handle; 9560 int ret; 9561 9562 if (!arg) { 9563 printf("Bad environment\n"); 9564 return -1; 9565 } 9566 offset = arg->offset; 9567 push_args(ctx, arg); 9568 ret = parse_int(ctx, token, str, len, buf, size); 9569 if (ret <= 0 || !ctx->object) 9570 return ret; 9571 if (ctx->port >= RTE_MAX_ETHPORTS) { 9572 printf("Bad port\n"); 9573 return -1; 9574 } 9575 if (offset == offsetof(struct rte_flow_item_flex, handle)) { 9576 const struct flex_item *fp; 9577 struct rte_flow_item_flex *item_flex = ctx->object; 9578 handle = (uint16_t)(uintptr_t)item_flex->handle; 9579 if (handle >= FLEX_MAX_PARSERS_NUM) { 9580 printf("Bad flex item handle\n"); 9581 return -1; 9582 } 9583 fp = flex_items[ctx->port][handle]; 9584 if (!fp) { 9585 printf("Bad flex item handle\n"); 9586 return -1; 9587 } 9588 item_flex->handle = fp->flex_handle; 9589 } else if (offset == offsetof(struct rte_flow_item_flex, pattern)) { 9590 handle = (uint16_t)(uintptr_t) 9591 ((struct rte_flow_item_flex *)ctx->object)->pattern; 9592 if (handle >= FLEX_MAX_PATTERNS_NUM) { 9593 printf("Bad pattern handle\n"); 9594 return -1; 9595 } 9596 src_spec = &flex_patterns[handle].spec; 9597 src_mask = &flex_patterns[handle].mask; 9598 spec = ctx->object; 9599 mask = spec + 2; /* spec, last, mask */ 9600 /* fill flow rule spec and mask parameters */ 9601 spec->length = src_spec->length; 9602 spec->pattern = src_spec->pattern; 9603 mask->length = src_mask->length; 9604 mask->pattern = src_mask->pattern; 9605 } else { 9606 printf("Bad arguments - unknown flex item offset\n"); 9607 return -1; 9608 } 9609 return ret; 9610 } 9611 9612 /** No completion. */ 9613 static int 9614 comp_none(struct context *ctx, const struct token *token, 9615 unsigned int ent, char *buf, unsigned int size) 9616 { 9617 (void)ctx; 9618 (void)token; 9619 (void)ent; 9620 (void)buf; 9621 (void)size; 9622 return 0; 9623 } 9624 9625 /** Complete boolean values. */ 9626 static int 9627 comp_boolean(struct context *ctx, const struct token *token, 9628 unsigned int ent, char *buf, unsigned int size) 9629 { 9630 unsigned int i; 9631 9632 (void)ctx; 9633 (void)token; 9634 for (i = 0; boolean_name[i]; ++i) 9635 if (buf && i == ent) 9636 return strlcpy(buf, boolean_name[i], size); 9637 if (buf) 9638 return -1; 9639 return i; 9640 } 9641 9642 /** Complete action names. */ 9643 static int 9644 comp_action(struct context *ctx, const struct token *token, 9645 unsigned int ent, char *buf, unsigned int size) 9646 { 9647 unsigned int i; 9648 9649 (void)ctx; 9650 (void)token; 9651 for (i = 0; next_action[i]; ++i) 9652 if (buf && i == ent) 9653 return strlcpy(buf, token_list[next_action[i]].name, 9654 size); 9655 if (buf) 9656 return -1; 9657 return i; 9658 } 9659 9660 /** Complete available ports. */ 9661 static int 9662 comp_port(struct context *ctx, const struct token *token, 9663 unsigned int ent, char *buf, unsigned int size) 9664 { 9665 unsigned int i = 0; 9666 portid_t p; 9667 9668 (void)ctx; 9669 (void)token; 9670 RTE_ETH_FOREACH_DEV(p) { 9671 if (buf && i == ent) 9672 return snprintf(buf, size, "%u", p); 9673 ++i; 9674 } 9675 if (buf) 9676 return -1; 9677 return i; 9678 } 9679 9680 /** Complete available rule IDs. */ 9681 static int 9682 comp_rule_id(struct context *ctx, const struct token *token, 9683 unsigned int ent, char *buf, unsigned int size) 9684 { 9685 unsigned int i = 0; 9686 struct rte_port *port; 9687 struct port_flow *pf; 9688 9689 (void)token; 9690 if (port_id_is_invalid(ctx->port, DISABLED_WARN) || 9691 ctx->port == (portid_t)RTE_PORT_ALL) 9692 return -1; 9693 port = &ports[ctx->port]; 9694 for (pf = port->flow_list; pf != NULL; pf = pf->next) { 9695 if (buf && i == ent) 9696 return snprintf(buf, size, "%u", pf->id); 9697 ++i; 9698 } 9699 if (buf) 9700 return -1; 9701 return i; 9702 } 9703 9704 /** Complete type field for RSS action. */ 9705 static int 9706 comp_vc_action_rss_type(struct context *ctx, const struct token *token, 9707 unsigned int ent, char *buf, unsigned int size) 9708 { 9709 unsigned int i; 9710 9711 (void)ctx; 9712 (void)token; 9713 for (i = 0; rss_type_table[i].str; ++i) 9714 ; 9715 if (!buf) 9716 return i + 1; 9717 if (ent < i) 9718 return strlcpy(buf, rss_type_table[ent].str, size); 9719 if (ent == i) 9720 return snprintf(buf, size, "end"); 9721 return -1; 9722 } 9723 9724 /** Complete queue field for RSS action. */ 9725 static int 9726 comp_vc_action_rss_queue(struct context *ctx, const struct token *token, 9727 unsigned int ent, char *buf, unsigned int size) 9728 { 9729 (void)ctx; 9730 (void)token; 9731 if (!buf) 9732 return nb_rxq + 1; 9733 if (ent < nb_rxq) 9734 return snprintf(buf, size, "%u", ent); 9735 if (ent == nb_rxq) 9736 return snprintf(buf, size, "end"); 9737 return -1; 9738 } 9739 9740 /** Complete index number for set raw_encap/raw_decap commands. */ 9741 static int 9742 comp_set_raw_index(struct context *ctx, const struct token *token, 9743 unsigned int ent, char *buf, unsigned int size) 9744 { 9745 uint16_t idx = 0; 9746 uint16_t nb = 0; 9747 9748 RTE_SET_USED(ctx); 9749 RTE_SET_USED(token); 9750 for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) { 9751 if (buf && idx == ent) 9752 return snprintf(buf, size, "%u", idx); 9753 ++nb; 9754 } 9755 return nb; 9756 } 9757 9758 /** Complete index number for set raw_encap/raw_decap commands. */ 9759 static int 9760 comp_set_sample_index(struct context *ctx, const struct token *token, 9761 unsigned int ent, char *buf, unsigned int size) 9762 { 9763 uint16_t idx = 0; 9764 uint16_t nb = 0; 9765 9766 RTE_SET_USED(ctx); 9767 RTE_SET_USED(token); 9768 for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) { 9769 if (buf && idx == ent) 9770 return snprintf(buf, size, "%u", idx); 9771 ++nb; 9772 } 9773 return nb; 9774 } 9775 9776 /** Complete operation for modify_field command. */ 9777 static int 9778 comp_set_modify_field_op(struct context *ctx, const struct token *token, 9779 unsigned int ent, char *buf, unsigned int size) 9780 { 9781 RTE_SET_USED(ctx); 9782 RTE_SET_USED(token); 9783 if (!buf) 9784 return RTE_DIM(modify_field_ops); 9785 if (ent < RTE_DIM(modify_field_ops) - 1) 9786 return strlcpy(buf, modify_field_ops[ent], size); 9787 return -1; 9788 } 9789 9790 /** Complete field id for modify_field command. */ 9791 static int 9792 comp_set_modify_field_id(struct context *ctx, const struct token *token, 9793 unsigned int ent, char *buf, unsigned int size) 9794 { 9795 const char *name; 9796 9797 RTE_SET_USED(token); 9798 if (!buf) 9799 return RTE_DIM(modify_field_ids); 9800 if (ent >= RTE_DIM(modify_field_ids) - 1) 9801 return -1; 9802 name = modify_field_ids[ent]; 9803 if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE || 9804 (strcmp(name, "pointer") && strcmp(name, "value"))) 9805 return strlcpy(buf, name, size); 9806 return -1; 9807 } 9808 9809 /** Complete available pattern template IDs. */ 9810 static int 9811 comp_pattern_template_id(struct context *ctx, const struct token *token, 9812 unsigned int ent, char *buf, unsigned int size) 9813 { 9814 unsigned int i = 0; 9815 struct rte_port *port; 9816 struct port_template *pt; 9817 9818 (void)token; 9819 if (port_id_is_invalid(ctx->port, DISABLED_WARN) || 9820 ctx->port == (portid_t)RTE_PORT_ALL) 9821 return -1; 9822 port = &ports[ctx->port]; 9823 for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) { 9824 if (buf && i == ent) 9825 return snprintf(buf, size, "%u", pt->id); 9826 ++i; 9827 } 9828 if (buf) 9829 return -1; 9830 return i; 9831 } 9832 9833 /** Complete available actions template IDs. */ 9834 static int 9835 comp_actions_template_id(struct context *ctx, const struct token *token, 9836 unsigned int ent, char *buf, unsigned int size) 9837 { 9838 unsigned int i = 0; 9839 struct rte_port *port; 9840 struct port_template *pt; 9841 9842 (void)token; 9843 if (port_id_is_invalid(ctx->port, DISABLED_WARN) || 9844 ctx->port == (portid_t)RTE_PORT_ALL) 9845 return -1; 9846 port = &ports[ctx->port]; 9847 for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) { 9848 if (buf && i == ent) 9849 return snprintf(buf, size, "%u", pt->id); 9850 ++i; 9851 } 9852 if (buf) 9853 return -1; 9854 return i; 9855 } 9856 9857 /** Complete available table IDs. */ 9858 static int 9859 comp_table_id(struct context *ctx, const struct token *token, 9860 unsigned int ent, char *buf, unsigned int size) 9861 { 9862 unsigned int i = 0; 9863 struct rte_port *port; 9864 struct port_table *pt; 9865 9866 (void)token; 9867 if (port_id_is_invalid(ctx->port, DISABLED_WARN) || 9868 ctx->port == (portid_t)RTE_PORT_ALL) 9869 return -1; 9870 port = &ports[ctx->port]; 9871 for (pt = port->table_list; pt != NULL; pt = pt->next) { 9872 if (buf && i == ent) 9873 return snprintf(buf, size, "%u", pt->id); 9874 ++i; 9875 } 9876 if (buf) 9877 return -1; 9878 return i; 9879 } 9880 9881 /** Complete available queue IDs. */ 9882 static int 9883 comp_queue_id(struct context *ctx, const struct token *token, 9884 unsigned int ent, char *buf, unsigned int size) 9885 { 9886 unsigned int i = 0; 9887 struct rte_port *port; 9888 9889 (void)token; 9890 if (port_id_is_invalid(ctx->port, DISABLED_WARN) || 9891 ctx->port == (portid_t)RTE_PORT_ALL) 9892 return -1; 9893 port = &ports[ctx->port]; 9894 for (i = 0; i < port->queue_nb; i++) { 9895 if (buf && i == ent) 9896 return snprintf(buf, size, "%u", i); 9897 } 9898 if (buf) 9899 return -1; 9900 return i; 9901 } 9902 9903 /** Internal context. */ 9904 static struct context cmd_flow_context; 9905 9906 /** Global parser instance (cmdline API). */ 9907 cmdline_parse_inst_t cmd_flow; 9908 cmdline_parse_inst_t cmd_set_raw; 9909 9910 /** Initialize context. */ 9911 static void 9912 cmd_flow_context_init(struct context *ctx) 9913 { 9914 /* A full memset() is not necessary. */ 9915 ctx->curr = ZERO; 9916 ctx->prev = ZERO; 9917 ctx->next_num = 0; 9918 ctx->args_num = 0; 9919 ctx->eol = 0; 9920 ctx->last = 0; 9921 ctx->port = 0; 9922 ctx->objdata = 0; 9923 ctx->object = NULL; 9924 ctx->objmask = NULL; 9925 } 9926 9927 /** Parse a token (cmdline API). */ 9928 static int 9929 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result, 9930 unsigned int size) 9931 { 9932 struct context *ctx = &cmd_flow_context; 9933 const struct token *token; 9934 const enum index *list; 9935 int len; 9936 int i; 9937 9938 (void)hdr; 9939 token = &token_list[ctx->curr]; 9940 /* Check argument length. */ 9941 ctx->eol = 0; 9942 ctx->last = 1; 9943 for (len = 0; src[len]; ++len) 9944 if (src[len] == '#' || isspace(src[len])) 9945 break; 9946 if (!len) 9947 return -1; 9948 /* Last argument and EOL detection. */ 9949 for (i = len; src[i]; ++i) 9950 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n') 9951 break; 9952 else if (!isspace(src[i])) { 9953 ctx->last = 0; 9954 break; 9955 } 9956 for (; src[i]; ++i) 9957 if (src[i] == '\r' || src[i] == '\n') { 9958 ctx->eol = 1; 9959 break; 9960 } 9961 /* Initialize context if necessary. */ 9962 if (!ctx->next_num) { 9963 if (!token->next) 9964 return 0; 9965 ctx->next[ctx->next_num++] = token->next[0]; 9966 } 9967 /* Process argument through candidates. */ 9968 ctx->prev = ctx->curr; 9969 list = ctx->next[ctx->next_num - 1]; 9970 for (i = 0; list[i]; ++i) { 9971 const struct token *next = &token_list[list[i]]; 9972 int tmp; 9973 9974 ctx->curr = list[i]; 9975 if (next->call) 9976 tmp = next->call(ctx, next, src, len, result, size); 9977 else 9978 tmp = parse_default(ctx, next, src, len, result, size); 9979 if (tmp == -1 || tmp != len) 9980 continue; 9981 token = next; 9982 break; 9983 } 9984 if (!list[i]) 9985 return -1; 9986 --ctx->next_num; 9987 /* Push subsequent tokens if any. */ 9988 if (token->next) 9989 for (i = 0; token->next[i]; ++i) { 9990 if (ctx->next_num == RTE_DIM(ctx->next)) 9991 return -1; 9992 ctx->next[ctx->next_num++] = token->next[i]; 9993 } 9994 /* Push arguments if any. */ 9995 if (token->args) 9996 for (i = 0; token->args[i]; ++i) { 9997 if (ctx->args_num == RTE_DIM(ctx->args)) 9998 return -1; 9999 ctx->args[ctx->args_num++] = token->args[i]; 10000 } 10001 return len; 10002 } 10003 10004 int 10005 flow_parse(const char *src, void *result, unsigned int size, 10006 struct rte_flow_attr **attr, 10007 struct rte_flow_item **pattern, struct rte_flow_action **actions) 10008 { 10009 int ret; 10010 struct context saved_flow_ctx = cmd_flow_context; 10011 10012 cmd_flow_context_init(&cmd_flow_context); 10013 do { 10014 ret = cmd_flow_parse(NULL, src, result, size); 10015 if (ret > 0) { 10016 src += ret; 10017 while (isspace(*src)) 10018 src++; 10019 } 10020 } while (ret > 0 && strlen(src)); 10021 cmd_flow_context = saved_flow_ctx; 10022 *attr = &((struct buffer *)result)->args.vc.attr; 10023 *pattern = ((struct buffer *)result)->args.vc.pattern; 10024 *actions = ((struct buffer *)result)->args.vc.actions; 10025 return (ret >= 0 && !strlen(src)) ? 0 : -1; 10026 } 10027 10028 /** Return number of completion entries (cmdline API). */ 10029 static int 10030 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr) 10031 { 10032 struct context *ctx = &cmd_flow_context; 10033 const struct token *token = &token_list[ctx->curr]; 10034 const enum index *list; 10035 int i; 10036 10037 (void)hdr; 10038 /* Count number of tokens in current list. */ 10039 if (ctx->next_num) 10040 list = ctx->next[ctx->next_num - 1]; 10041 else 10042 list = token->next[0]; 10043 for (i = 0; list[i]; ++i) 10044 ; 10045 if (!i) 10046 return 0; 10047 /* 10048 * If there is a single token, use its completion callback, otherwise 10049 * return the number of entries. 10050 */ 10051 token = &token_list[list[0]]; 10052 if (i == 1 && token->comp) { 10053 /* Save index for cmd_flow_get_help(). */ 10054 ctx->prev = list[0]; 10055 return token->comp(ctx, token, 0, NULL, 0); 10056 } 10057 return i; 10058 } 10059 10060 /** Return a completion entry (cmdline API). */ 10061 static int 10062 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index, 10063 char *dst, unsigned int size) 10064 { 10065 struct context *ctx = &cmd_flow_context; 10066 const struct token *token = &token_list[ctx->curr]; 10067 const enum index *list; 10068 int i; 10069 10070 (void)hdr; 10071 /* Count number of tokens in current list. */ 10072 if (ctx->next_num) 10073 list = ctx->next[ctx->next_num - 1]; 10074 else 10075 list = token->next[0]; 10076 for (i = 0; list[i]; ++i) 10077 ; 10078 if (!i) 10079 return -1; 10080 /* If there is a single token, use its completion callback. */ 10081 token = &token_list[list[0]]; 10082 if (i == 1 && token->comp) { 10083 /* Save index for cmd_flow_get_help(). */ 10084 ctx->prev = list[0]; 10085 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0; 10086 } 10087 /* Otherwise make sure the index is valid and use defaults. */ 10088 if (index >= i) 10089 return -1; 10090 token = &token_list[list[index]]; 10091 strlcpy(dst, token->name, size); 10092 /* Save index for cmd_flow_get_help(). */ 10093 ctx->prev = list[index]; 10094 return 0; 10095 } 10096 10097 /** Populate help strings for current token (cmdline API). */ 10098 static int 10099 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size) 10100 { 10101 struct context *ctx = &cmd_flow_context; 10102 const struct token *token = &token_list[ctx->prev]; 10103 10104 (void)hdr; 10105 if (!size) 10106 return -1; 10107 /* Set token type and update global help with details. */ 10108 strlcpy(dst, (token->type ? token->type : "TOKEN"), size); 10109 if (token->help) 10110 cmd_flow.help_str = token->help; 10111 else 10112 cmd_flow.help_str = token->name; 10113 return 0; 10114 } 10115 10116 /** Token definition template (cmdline API). */ 10117 static struct cmdline_token_hdr cmd_flow_token_hdr = { 10118 .ops = &(struct cmdline_token_ops){ 10119 .parse = cmd_flow_parse, 10120 .complete_get_nb = cmd_flow_complete_get_nb, 10121 .complete_get_elt = cmd_flow_complete_get_elt, 10122 .get_help = cmd_flow_get_help, 10123 }, 10124 .offset = 0, 10125 }; 10126 10127 /** Populate the next dynamic token. */ 10128 static void 10129 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr, 10130 cmdline_parse_token_hdr_t **hdr_inst) 10131 { 10132 struct context *ctx = &cmd_flow_context; 10133 10134 /* Always reinitialize context before requesting the first token. */ 10135 if (!(hdr_inst - cmd_flow.tokens)) 10136 cmd_flow_context_init(ctx); 10137 /* Return NULL when no more tokens are expected. */ 10138 if (!ctx->next_num && ctx->curr) { 10139 *hdr = NULL; 10140 return; 10141 } 10142 /* Determine if command should end here. */ 10143 if (ctx->eol && ctx->last && ctx->next_num) { 10144 const enum index *list = ctx->next[ctx->next_num - 1]; 10145 int i; 10146 10147 for (i = 0; list[i]; ++i) { 10148 if (list[i] != END) 10149 continue; 10150 *hdr = NULL; 10151 return; 10152 } 10153 } 10154 *hdr = &cmd_flow_token_hdr; 10155 } 10156 10157 /** Dispatch parsed buffer to function calls. */ 10158 static void 10159 cmd_flow_parsed(const struct buffer *in) 10160 { 10161 switch (in->command) { 10162 case INFO: 10163 port_flow_get_info(in->port); 10164 break; 10165 case CONFIGURE: 10166 port_flow_configure(in->port, 10167 &in->args.configure.port_attr, 10168 in->args.configure.nb_queue, 10169 &in->args.configure.queue_attr); 10170 break; 10171 case PATTERN_TEMPLATE_CREATE: 10172 port_flow_pattern_template_create(in->port, 10173 in->args.vc.pat_templ_id, 10174 &((const struct rte_flow_pattern_template_attr) { 10175 .relaxed_matching = in->args.vc.attr.reserved, 10176 .ingress = in->args.vc.attr.ingress, 10177 .egress = in->args.vc.attr.egress, 10178 .transfer = in->args.vc.attr.transfer, 10179 }), 10180 in->args.vc.pattern); 10181 break; 10182 case PATTERN_TEMPLATE_DESTROY: 10183 port_flow_pattern_template_destroy(in->port, 10184 in->args.templ_destroy.template_id_n, 10185 in->args.templ_destroy.template_id); 10186 break; 10187 case ACTIONS_TEMPLATE_CREATE: 10188 port_flow_actions_template_create(in->port, 10189 in->args.vc.act_templ_id, 10190 &((const struct rte_flow_actions_template_attr) { 10191 .ingress = in->args.vc.attr.ingress, 10192 .egress = in->args.vc.attr.egress, 10193 .transfer = in->args.vc.attr.transfer, 10194 }), 10195 in->args.vc.actions, 10196 in->args.vc.masks); 10197 break; 10198 case ACTIONS_TEMPLATE_DESTROY: 10199 port_flow_actions_template_destroy(in->port, 10200 in->args.templ_destroy.template_id_n, 10201 in->args.templ_destroy.template_id); 10202 break; 10203 case TABLE_CREATE: 10204 port_flow_template_table_create(in->port, in->args.table.id, 10205 &in->args.table.attr, in->args.table.pat_templ_id_n, 10206 in->args.table.pat_templ_id, in->args.table.act_templ_id_n, 10207 in->args.table.act_templ_id); 10208 break; 10209 case TABLE_DESTROY: 10210 port_flow_template_table_destroy(in->port, 10211 in->args.table_destroy.table_id_n, 10212 in->args.table_destroy.table_id); 10213 break; 10214 case QUEUE_CREATE: 10215 port_queue_flow_create(in->port, in->queue, in->postpone, 10216 in->args.vc.table_id, in->args.vc.pat_templ_id, 10217 in->args.vc.act_templ_id, in->args.vc.pattern, 10218 in->args.vc.actions); 10219 break; 10220 case QUEUE_DESTROY: 10221 port_queue_flow_destroy(in->port, in->queue, in->postpone, 10222 in->args.destroy.rule_n, 10223 in->args.destroy.rule); 10224 break; 10225 case PUSH: 10226 port_queue_flow_push(in->port, in->queue); 10227 break; 10228 case PULL: 10229 port_queue_flow_pull(in->port, in->queue); 10230 break; 10231 case INDIRECT_ACTION_CREATE: 10232 port_action_handle_create( 10233 in->port, in->args.vc.attr.group, 10234 &((const struct rte_flow_indir_action_conf) { 10235 .ingress = in->args.vc.attr.ingress, 10236 .egress = in->args.vc.attr.egress, 10237 .transfer = in->args.vc.attr.transfer, 10238 }), 10239 in->args.vc.actions); 10240 break; 10241 case INDIRECT_ACTION_DESTROY: 10242 port_action_handle_destroy(in->port, 10243 in->args.ia_destroy.action_id_n, 10244 in->args.ia_destroy.action_id); 10245 break; 10246 case INDIRECT_ACTION_UPDATE: 10247 port_action_handle_update(in->port, in->args.vc.attr.group, 10248 in->args.vc.actions); 10249 break; 10250 case INDIRECT_ACTION_QUERY: 10251 port_action_handle_query(in->port, in->args.ia.action_id); 10252 break; 10253 case VALIDATE: 10254 port_flow_validate(in->port, &in->args.vc.attr, 10255 in->args.vc.pattern, in->args.vc.actions, 10256 &in->args.vc.tunnel_ops); 10257 break; 10258 case CREATE: 10259 port_flow_create(in->port, &in->args.vc.attr, 10260 in->args.vc.pattern, in->args.vc.actions, 10261 &in->args.vc.tunnel_ops); 10262 break; 10263 case DESTROY: 10264 port_flow_destroy(in->port, in->args.destroy.rule_n, 10265 in->args.destroy.rule); 10266 break; 10267 case FLUSH: 10268 port_flow_flush(in->port); 10269 break; 10270 case DUMP_ONE: 10271 case DUMP_ALL: 10272 port_flow_dump(in->port, in->args.dump.mode, 10273 in->args.dump.rule, in->args.dump.file); 10274 break; 10275 case QUERY: 10276 port_flow_query(in->port, in->args.query.rule, 10277 &in->args.query.action); 10278 break; 10279 case LIST: 10280 port_flow_list(in->port, in->args.list.group_n, 10281 in->args.list.group); 10282 break; 10283 case ISOLATE: 10284 port_flow_isolate(in->port, in->args.isolate.set); 10285 break; 10286 case AGED: 10287 port_flow_aged(in->port, in->args.aged.destroy); 10288 break; 10289 case TUNNEL_CREATE: 10290 port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops); 10291 break; 10292 case TUNNEL_DESTROY: 10293 port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id); 10294 break; 10295 case TUNNEL_LIST: 10296 port_flow_tunnel_list(in->port); 10297 break; 10298 case ACTION_POL_G: 10299 port_meter_policy_add(in->port, in->args.policy.policy_id, 10300 in->args.vc.actions); 10301 break; 10302 case FLEX_ITEM_CREATE: 10303 flex_item_create(in->port, in->args.flex.token, 10304 in->args.flex.filename); 10305 break; 10306 case FLEX_ITEM_DESTROY: 10307 flex_item_destroy(in->port, in->args.flex.token); 10308 break; 10309 default: 10310 break; 10311 } 10312 } 10313 10314 /** Token generator and output processing callback (cmdline API). */ 10315 static void 10316 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2) 10317 { 10318 if (cl == NULL) 10319 cmd_flow_tok(arg0, arg2); 10320 else 10321 cmd_flow_parsed(arg0); 10322 } 10323 10324 /** Global parser instance (cmdline API). */ 10325 cmdline_parse_inst_t cmd_flow = { 10326 .f = cmd_flow_cb, 10327 .data = NULL, /**< Unused. */ 10328 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */ 10329 .tokens = { 10330 NULL, 10331 }, /**< Tokens are returned by cmd_flow_tok(). */ 10332 }; 10333 10334 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */ 10335 10336 static void 10337 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto) 10338 { 10339 struct rte_ipv4_hdr *ipv4; 10340 struct rte_ether_hdr *eth; 10341 struct rte_ipv6_hdr *ipv6; 10342 struct rte_vxlan_hdr *vxlan; 10343 struct rte_vxlan_gpe_hdr *gpe; 10344 struct rte_flow_item_nvgre *nvgre; 10345 uint32_t ipv6_vtc_flow; 10346 10347 switch (item->type) { 10348 case RTE_FLOW_ITEM_TYPE_ETH: 10349 eth = (struct rte_ether_hdr *)buf; 10350 if (next_proto) 10351 eth->ether_type = rte_cpu_to_be_16(next_proto); 10352 break; 10353 case RTE_FLOW_ITEM_TYPE_IPV4: 10354 ipv4 = (struct rte_ipv4_hdr *)buf; 10355 if (!ipv4->version_ihl) 10356 ipv4->version_ihl = RTE_IPV4_VHL_DEF; 10357 if (next_proto && ipv4->next_proto_id == 0) 10358 ipv4->next_proto_id = (uint8_t)next_proto; 10359 break; 10360 case RTE_FLOW_ITEM_TYPE_IPV6: 10361 ipv6 = (struct rte_ipv6_hdr *)buf; 10362 if (next_proto && ipv6->proto == 0) 10363 ipv6->proto = (uint8_t)next_proto; 10364 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow); 10365 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */ 10366 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */ 10367 ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow); 10368 break; 10369 case RTE_FLOW_ITEM_TYPE_VXLAN: 10370 vxlan = (struct rte_vxlan_hdr *)buf; 10371 vxlan->vx_flags = 0x08; 10372 break; 10373 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 10374 gpe = (struct rte_vxlan_gpe_hdr *)buf; 10375 gpe->vx_flags = 0x0C; 10376 break; 10377 case RTE_FLOW_ITEM_TYPE_NVGRE: 10378 nvgre = (struct rte_flow_item_nvgre *)buf; 10379 nvgre->protocol = rte_cpu_to_be_16(0x6558); 10380 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000); 10381 break; 10382 default: 10383 break; 10384 } 10385 } 10386 10387 /** Helper of get item's default mask. */ 10388 static const void * 10389 flow_item_default_mask(const struct rte_flow_item *item) 10390 { 10391 const void *mask = NULL; 10392 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX); 10393 10394 switch (item->type) { 10395 case RTE_FLOW_ITEM_TYPE_ANY: 10396 mask = &rte_flow_item_any_mask; 10397 break; 10398 case RTE_FLOW_ITEM_TYPE_VF: 10399 mask = &rte_flow_item_vf_mask; 10400 break; 10401 case RTE_FLOW_ITEM_TYPE_PORT_ID: 10402 mask = &rte_flow_item_port_id_mask; 10403 break; 10404 case RTE_FLOW_ITEM_TYPE_RAW: 10405 mask = &rte_flow_item_raw_mask; 10406 break; 10407 case RTE_FLOW_ITEM_TYPE_ETH: 10408 mask = &rte_flow_item_eth_mask; 10409 break; 10410 case RTE_FLOW_ITEM_TYPE_VLAN: 10411 mask = &rte_flow_item_vlan_mask; 10412 break; 10413 case RTE_FLOW_ITEM_TYPE_IPV4: 10414 mask = &rte_flow_item_ipv4_mask; 10415 break; 10416 case RTE_FLOW_ITEM_TYPE_IPV6: 10417 mask = &rte_flow_item_ipv6_mask; 10418 break; 10419 case RTE_FLOW_ITEM_TYPE_ICMP: 10420 mask = &rte_flow_item_icmp_mask; 10421 break; 10422 case RTE_FLOW_ITEM_TYPE_UDP: 10423 mask = &rte_flow_item_udp_mask; 10424 break; 10425 case RTE_FLOW_ITEM_TYPE_TCP: 10426 mask = &rte_flow_item_tcp_mask; 10427 break; 10428 case RTE_FLOW_ITEM_TYPE_SCTP: 10429 mask = &rte_flow_item_sctp_mask; 10430 break; 10431 case RTE_FLOW_ITEM_TYPE_VXLAN: 10432 mask = &rte_flow_item_vxlan_mask; 10433 break; 10434 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 10435 mask = &rte_flow_item_vxlan_gpe_mask; 10436 break; 10437 case RTE_FLOW_ITEM_TYPE_E_TAG: 10438 mask = &rte_flow_item_e_tag_mask; 10439 break; 10440 case RTE_FLOW_ITEM_TYPE_NVGRE: 10441 mask = &rte_flow_item_nvgre_mask; 10442 break; 10443 case RTE_FLOW_ITEM_TYPE_MPLS: 10444 mask = &rte_flow_item_mpls_mask; 10445 break; 10446 case RTE_FLOW_ITEM_TYPE_GRE: 10447 mask = &rte_flow_item_gre_mask; 10448 break; 10449 case RTE_FLOW_ITEM_TYPE_GRE_KEY: 10450 mask = &gre_key_default_mask; 10451 break; 10452 case RTE_FLOW_ITEM_TYPE_META: 10453 mask = &rte_flow_item_meta_mask; 10454 break; 10455 case RTE_FLOW_ITEM_TYPE_FUZZY: 10456 mask = &rte_flow_item_fuzzy_mask; 10457 break; 10458 case RTE_FLOW_ITEM_TYPE_GTP: 10459 mask = &rte_flow_item_gtp_mask; 10460 break; 10461 case RTE_FLOW_ITEM_TYPE_GTP_PSC: 10462 mask = &rte_flow_item_gtp_psc_mask; 10463 break; 10464 case RTE_FLOW_ITEM_TYPE_GENEVE: 10465 mask = &rte_flow_item_geneve_mask; 10466 break; 10467 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT: 10468 mask = &rte_flow_item_geneve_opt_mask; 10469 break; 10470 case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID: 10471 mask = &rte_flow_item_pppoe_proto_id_mask; 10472 break; 10473 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP: 10474 mask = &rte_flow_item_l2tpv3oip_mask; 10475 break; 10476 case RTE_FLOW_ITEM_TYPE_ESP: 10477 mask = &rte_flow_item_esp_mask; 10478 break; 10479 case RTE_FLOW_ITEM_TYPE_AH: 10480 mask = &rte_flow_item_ah_mask; 10481 break; 10482 case RTE_FLOW_ITEM_TYPE_PFCP: 10483 mask = &rte_flow_item_pfcp_mask; 10484 break; 10485 case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR: 10486 case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT: 10487 mask = &rte_flow_item_ethdev_mask; 10488 break; 10489 case RTE_FLOW_ITEM_TYPE_L2TPV2: 10490 mask = &rte_flow_item_l2tpv2_mask; 10491 break; 10492 case RTE_FLOW_ITEM_TYPE_PPP: 10493 mask = &rte_flow_item_ppp_mask; 10494 break; 10495 default: 10496 break; 10497 } 10498 return mask; 10499 } 10500 10501 /** Dispatch parsed buffer to function calls. */ 10502 static void 10503 cmd_set_raw_parsed_sample(const struct buffer *in) 10504 { 10505 uint32_t n = in->args.vc.actions_n; 10506 uint32_t i = 0; 10507 struct rte_flow_action *action = NULL; 10508 struct rte_flow_action *data = NULL; 10509 const struct rte_flow_action_rss *rss = NULL; 10510 size_t size = 0; 10511 uint16_t idx = in->port; /* We borrow port field as index */ 10512 uint32_t max_size = sizeof(struct rte_flow_action) * 10513 ACTION_SAMPLE_ACTIONS_NUM; 10514 10515 RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS); 10516 data = (struct rte_flow_action *)&raw_sample_confs[idx].data; 10517 memset(data, 0x00, max_size); 10518 for (; i <= n - 1; i++) { 10519 action = in->args.vc.actions + i; 10520 if (action->type == RTE_FLOW_ACTION_TYPE_END) 10521 break; 10522 switch (action->type) { 10523 case RTE_FLOW_ACTION_TYPE_MARK: 10524 size = sizeof(struct rte_flow_action_mark); 10525 rte_memcpy(&sample_mark[idx], 10526 (const void *)action->conf, size); 10527 action->conf = &sample_mark[idx]; 10528 break; 10529 case RTE_FLOW_ACTION_TYPE_COUNT: 10530 size = sizeof(struct rte_flow_action_count); 10531 rte_memcpy(&sample_count[idx], 10532 (const void *)action->conf, size); 10533 action->conf = &sample_count[idx]; 10534 break; 10535 case RTE_FLOW_ACTION_TYPE_QUEUE: 10536 size = sizeof(struct rte_flow_action_queue); 10537 rte_memcpy(&sample_queue[idx], 10538 (const void *)action->conf, size); 10539 action->conf = &sample_queue[idx]; 10540 break; 10541 case RTE_FLOW_ACTION_TYPE_RSS: 10542 size = sizeof(struct rte_flow_action_rss); 10543 rss = action->conf; 10544 rte_memcpy(&sample_rss_data[idx].conf, 10545 (const void *)rss, size); 10546 if (rss->key_len && rss->key) { 10547 sample_rss_data[idx].conf.key = 10548 sample_rss_data[idx].key; 10549 rte_memcpy((void *)((uintptr_t) 10550 sample_rss_data[idx].conf.key), 10551 (const void *)rss->key, 10552 sizeof(uint8_t) * rss->key_len); 10553 } 10554 if (rss->queue_num && rss->queue) { 10555 sample_rss_data[idx].conf.queue = 10556 sample_rss_data[idx].queue; 10557 rte_memcpy((void *)((uintptr_t) 10558 sample_rss_data[idx].conf.queue), 10559 (const void *)rss->queue, 10560 sizeof(uint16_t) * rss->queue_num); 10561 } 10562 action->conf = &sample_rss_data[idx].conf; 10563 break; 10564 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 10565 size = sizeof(struct rte_flow_action_raw_encap); 10566 rte_memcpy(&sample_encap[idx], 10567 (const void *)action->conf, size); 10568 action->conf = &sample_encap[idx]; 10569 break; 10570 case RTE_FLOW_ACTION_TYPE_PORT_ID: 10571 size = sizeof(struct rte_flow_action_port_id); 10572 rte_memcpy(&sample_port_id[idx], 10573 (const void *)action->conf, size); 10574 action->conf = &sample_port_id[idx]; 10575 break; 10576 case RTE_FLOW_ACTION_TYPE_PF: 10577 break; 10578 case RTE_FLOW_ACTION_TYPE_VF: 10579 size = sizeof(struct rte_flow_action_vf); 10580 rte_memcpy(&sample_vf[idx], 10581 (const void *)action->conf, size); 10582 action->conf = &sample_vf[idx]; 10583 break; 10584 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: 10585 size = sizeof(struct rte_flow_action_vxlan_encap); 10586 parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]); 10587 action->conf = &sample_vxlan_encap[idx].conf; 10588 break; 10589 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP: 10590 size = sizeof(struct rte_flow_action_nvgre_encap); 10591 parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]); 10592 action->conf = &sample_nvgre_encap[idx]; 10593 break; 10594 default: 10595 fprintf(stderr, "Error - Not supported action\n"); 10596 return; 10597 } 10598 rte_memcpy(data, action, sizeof(struct rte_flow_action)); 10599 data++; 10600 } 10601 } 10602 10603 /** Dispatch parsed buffer to function calls. */ 10604 static void 10605 cmd_set_raw_parsed(const struct buffer *in) 10606 { 10607 uint32_t n = in->args.vc.pattern_n; 10608 int i = 0; 10609 struct rte_flow_item *item = NULL; 10610 size_t size = 0; 10611 uint8_t *data = NULL; 10612 uint8_t *data_tail = NULL; 10613 size_t *total_size = NULL; 10614 uint16_t upper_layer = 0; 10615 uint16_t proto = 0; 10616 uint16_t idx = in->port; /* We borrow port field as index */ 10617 int gtp_psc = -1; /* GTP PSC option index. */ 10618 10619 if (in->command == SET_SAMPLE_ACTIONS) 10620 return cmd_set_raw_parsed_sample(in); 10621 RTE_ASSERT(in->command == SET_RAW_ENCAP || 10622 in->command == SET_RAW_DECAP); 10623 if (in->command == SET_RAW_ENCAP) { 10624 total_size = &raw_encap_confs[idx].size; 10625 data = (uint8_t *)&raw_encap_confs[idx].data; 10626 } else { 10627 total_size = &raw_decap_confs[idx].size; 10628 data = (uint8_t *)&raw_decap_confs[idx].data; 10629 } 10630 *total_size = 0; 10631 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA); 10632 /* process hdr from upper layer to low layer (L3/L4 -> L2). */ 10633 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA; 10634 for (i = n - 1 ; i >= 0; --i) { 10635 const struct rte_flow_item_gtp *gtp; 10636 const struct rte_flow_item_geneve_opt *opt; 10637 10638 item = in->args.vc.pattern + i; 10639 if (item->spec == NULL) 10640 item->spec = flow_item_default_mask(item); 10641 switch (item->type) { 10642 case RTE_FLOW_ITEM_TYPE_ETH: 10643 size = sizeof(struct rte_ether_hdr); 10644 break; 10645 case RTE_FLOW_ITEM_TYPE_VLAN: 10646 size = sizeof(struct rte_vlan_hdr); 10647 proto = RTE_ETHER_TYPE_VLAN; 10648 break; 10649 case RTE_FLOW_ITEM_TYPE_IPV4: 10650 size = sizeof(struct rte_ipv4_hdr); 10651 proto = RTE_ETHER_TYPE_IPV4; 10652 break; 10653 case RTE_FLOW_ITEM_TYPE_IPV6: 10654 size = sizeof(struct rte_ipv6_hdr); 10655 proto = RTE_ETHER_TYPE_IPV6; 10656 break; 10657 case RTE_FLOW_ITEM_TYPE_UDP: 10658 size = sizeof(struct rte_udp_hdr); 10659 proto = 0x11; 10660 break; 10661 case RTE_FLOW_ITEM_TYPE_TCP: 10662 size = sizeof(struct rte_tcp_hdr); 10663 proto = 0x06; 10664 break; 10665 case RTE_FLOW_ITEM_TYPE_VXLAN: 10666 size = sizeof(struct rte_vxlan_hdr); 10667 break; 10668 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 10669 size = sizeof(struct rte_vxlan_gpe_hdr); 10670 break; 10671 case RTE_FLOW_ITEM_TYPE_GRE: 10672 size = sizeof(struct rte_gre_hdr); 10673 proto = 0x2F; 10674 break; 10675 case RTE_FLOW_ITEM_TYPE_GRE_KEY: 10676 size = sizeof(rte_be32_t); 10677 proto = 0x0; 10678 break; 10679 case RTE_FLOW_ITEM_TYPE_MPLS: 10680 size = sizeof(struct rte_mpls_hdr); 10681 proto = 0x0; 10682 break; 10683 case RTE_FLOW_ITEM_TYPE_NVGRE: 10684 size = sizeof(struct rte_flow_item_nvgre); 10685 proto = 0x2F; 10686 break; 10687 case RTE_FLOW_ITEM_TYPE_GENEVE: 10688 size = sizeof(struct rte_geneve_hdr); 10689 break; 10690 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT: 10691 opt = (const struct rte_flow_item_geneve_opt *) 10692 item->spec; 10693 size = offsetof(struct rte_flow_item_geneve_opt, data); 10694 if (opt->option_len && opt->data) { 10695 *total_size += opt->option_len * 10696 sizeof(uint32_t); 10697 rte_memcpy(data_tail - (*total_size), 10698 opt->data, 10699 opt->option_len * sizeof(uint32_t)); 10700 } 10701 break; 10702 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP: 10703 size = sizeof(rte_be32_t); 10704 proto = 0x73; 10705 break; 10706 case RTE_FLOW_ITEM_TYPE_ESP: 10707 size = sizeof(struct rte_esp_hdr); 10708 proto = 0x32; 10709 break; 10710 case RTE_FLOW_ITEM_TYPE_AH: 10711 size = sizeof(struct rte_flow_item_ah); 10712 proto = 0x33; 10713 break; 10714 case RTE_FLOW_ITEM_TYPE_GTP: 10715 if (gtp_psc < 0) { 10716 size = sizeof(struct rte_gtp_hdr); 10717 break; 10718 } 10719 if (gtp_psc != i + 1) { 10720 fprintf(stderr, 10721 "Error - GTP PSC does not follow GTP\n"); 10722 goto error; 10723 } 10724 gtp = item->spec; 10725 if ((gtp->v_pt_rsv_flags & 0x07) != 0x04) { 10726 /* Only E flag should be set. */ 10727 fprintf(stderr, 10728 "Error - GTP unsupported flags\n"); 10729 goto error; 10730 } else { 10731 struct rte_gtp_hdr_ext_word ext_word = { 10732 .next_ext = 0x85 10733 }; 10734 10735 /* We have to add GTP header extra word. */ 10736 *total_size += sizeof(ext_word); 10737 rte_memcpy(data_tail - (*total_size), 10738 &ext_word, sizeof(ext_word)); 10739 } 10740 size = sizeof(struct rte_gtp_hdr); 10741 break; 10742 case RTE_FLOW_ITEM_TYPE_GTP_PSC: 10743 if (gtp_psc >= 0) { 10744 fprintf(stderr, 10745 "Error - Multiple GTP PSC items\n"); 10746 goto error; 10747 } else { 10748 const struct rte_flow_item_gtp_psc 10749 *opt = item->spec; 10750 struct { 10751 uint8_t len; 10752 uint8_t pdu_type:4; 10753 uint8_t qfi:6; 10754 uint8_t next; 10755 } psc; 10756 psc.len = sizeof(psc) / 4; 10757 psc.pdu_type = opt->hdr.type; 10758 psc.qfi = opt->hdr.qfi; 10759 psc.next = 0; 10760 *total_size += sizeof(psc); 10761 rte_memcpy(data_tail - (*total_size), 10762 &psc, sizeof(psc)); 10763 gtp_psc = i; 10764 size = 0; 10765 } 10766 break; 10767 case RTE_FLOW_ITEM_TYPE_PFCP: 10768 size = sizeof(struct rte_flow_item_pfcp); 10769 break; 10770 case RTE_FLOW_ITEM_TYPE_FLEX: 10771 size = item->spec ? 10772 ((const struct rte_flow_item_flex *) 10773 item->spec)->length : 0; 10774 break; 10775 case RTE_FLOW_ITEM_TYPE_GRE_OPTION: 10776 size = 0; 10777 if (item->spec) { 10778 const struct rte_flow_item_gre_opt 10779 *opt = item->spec; 10780 if (opt->checksum_rsvd.checksum) { 10781 *total_size += 10782 sizeof(opt->checksum_rsvd); 10783 rte_memcpy(data_tail - (*total_size), 10784 &opt->checksum_rsvd, 10785 sizeof(opt->checksum_rsvd)); 10786 } 10787 if (opt->key.key) { 10788 *total_size += sizeof(opt->key.key); 10789 rte_memcpy(data_tail - (*total_size), 10790 &opt->key.key, 10791 sizeof(opt->key.key)); 10792 } 10793 if (opt->sequence.sequence) { 10794 *total_size += sizeof(opt->sequence.sequence); 10795 rte_memcpy(data_tail - (*total_size), 10796 &opt->sequence.sequence, 10797 sizeof(opt->sequence.sequence)); 10798 } 10799 } 10800 proto = 0x2F; 10801 break; 10802 default: 10803 fprintf(stderr, "Error - Not supported item\n"); 10804 goto error; 10805 } 10806 *total_size += size; 10807 rte_memcpy(data_tail - (*total_size), item->spec, size); 10808 /* update some fields which cannot be set by cmdline */ 10809 update_fields((data_tail - (*total_size)), item, 10810 upper_layer); 10811 upper_layer = proto; 10812 } 10813 if (verbose_level & 0x1) 10814 printf("total data size is %zu\n", (*total_size)); 10815 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA); 10816 memmove(data, (data_tail - (*total_size)), *total_size); 10817 return; 10818 10819 error: 10820 *total_size = 0; 10821 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA); 10822 } 10823 10824 /** Populate help strings for current token (cmdline API). */ 10825 static int 10826 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, 10827 unsigned int size) 10828 { 10829 struct context *ctx = &cmd_flow_context; 10830 const struct token *token = &token_list[ctx->prev]; 10831 10832 (void)hdr; 10833 if (!size) 10834 return -1; 10835 /* Set token type and update global help with details. */ 10836 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN")); 10837 if (token->help) 10838 cmd_set_raw.help_str = token->help; 10839 else 10840 cmd_set_raw.help_str = token->name; 10841 return 0; 10842 } 10843 10844 /** Token definition template (cmdline API). */ 10845 static struct cmdline_token_hdr cmd_set_raw_token_hdr = { 10846 .ops = &(struct cmdline_token_ops){ 10847 .parse = cmd_flow_parse, 10848 .complete_get_nb = cmd_flow_complete_get_nb, 10849 .complete_get_elt = cmd_flow_complete_get_elt, 10850 .get_help = cmd_set_raw_get_help, 10851 }, 10852 .offset = 0, 10853 }; 10854 10855 /** Populate the next dynamic token. */ 10856 static void 10857 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr, 10858 cmdline_parse_token_hdr_t **hdr_inst) 10859 { 10860 struct context *ctx = &cmd_flow_context; 10861 10862 /* Always reinitialize context before requesting the first token. */ 10863 if (!(hdr_inst - cmd_set_raw.tokens)) { 10864 cmd_flow_context_init(ctx); 10865 ctx->curr = START_SET; 10866 } 10867 /* Return NULL when no more tokens are expected. */ 10868 if (!ctx->next_num && (ctx->curr != START_SET)) { 10869 *hdr = NULL; 10870 return; 10871 } 10872 /* Determine if command should end here. */ 10873 if (ctx->eol && ctx->last && ctx->next_num) { 10874 const enum index *list = ctx->next[ctx->next_num - 1]; 10875 int i; 10876 10877 for (i = 0; list[i]; ++i) { 10878 if (list[i] != END) 10879 continue; 10880 *hdr = NULL; 10881 return; 10882 } 10883 } 10884 *hdr = &cmd_set_raw_token_hdr; 10885 } 10886 10887 /** Token generator and output processing callback (cmdline API). */ 10888 static void 10889 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2) 10890 { 10891 if (cl == NULL) 10892 cmd_set_raw_tok(arg0, arg2); 10893 else 10894 cmd_set_raw_parsed(arg0); 10895 } 10896 10897 /** Global parser instance (cmdline API). */ 10898 cmdline_parse_inst_t cmd_set_raw = { 10899 .f = cmd_set_raw_cb, 10900 .data = NULL, /**< Unused. */ 10901 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */ 10902 .tokens = { 10903 NULL, 10904 }, /**< Tokens are returned by cmd_flow_tok(). */ 10905 }; 10906 10907 /* *** display raw_encap/raw_decap buf */ 10908 struct cmd_show_set_raw_result { 10909 cmdline_fixed_string_t cmd_show; 10910 cmdline_fixed_string_t cmd_what; 10911 cmdline_fixed_string_t cmd_all; 10912 uint16_t cmd_index; 10913 }; 10914 10915 static void 10916 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data) 10917 { 10918 struct cmd_show_set_raw_result *res = parsed_result; 10919 uint16_t index = res->cmd_index; 10920 uint8_t all = 0; 10921 uint8_t *raw_data = NULL; 10922 size_t raw_size = 0; 10923 char title[16] = {0}; 10924 10925 RTE_SET_USED(cl); 10926 RTE_SET_USED(data); 10927 if (!strcmp(res->cmd_all, "all")) { 10928 all = 1; 10929 index = 0; 10930 } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) { 10931 fprintf(stderr, "index should be 0-%u\n", 10932 RAW_ENCAP_CONFS_MAX_NUM - 1); 10933 return; 10934 } 10935 do { 10936 if (!strcmp(res->cmd_what, "raw_encap")) { 10937 raw_data = (uint8_t *)&raw_encap_confs[index].data; 10938 raw_size = raw_encap_confs[index].size; 10939 snprintf(title, 16, "\nindex: %u", index); 10940 rte_hexdump(stdout, title, raw_data, raw_size); 10941 } else { 10942 raw_data = (uint8_t *)&raw_decap_confs[index].data; 10943 raw_size = raw_decap_confs[index].size; 10944 snprintf(title, 16, "\nindex: %u", index); 10945 rte_hexdump(stdout, title, raw_data, raw_size); 10946 } 10947 } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM); 10948 } 10949 10950 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show = 10951 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, 10952 cmd_show, "show"); 10953 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what = 10954 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, 10955 cmd_what, "raw_encap#raw_decap"); 10956 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index = 10957 TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result, 10958 cmd_index, RTE_UINT16); 10959 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all = 10960 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, 10961 cmd_all, "all"); 10962 cmdline_parse_inst_t cmd_show_set_raw = { 10963 .f = cmd_show_set_raw_parsed, 10964 .data = NULL, 10965 .help_str = "show <raw_encap|raw_decap> <index>", 10966 .tokens = { 10967 (void *)&cmd_show_set_raw_cmd_show, 10968 (void *)&cmd_show_set_raw_cmd_what, 10969 (void *)&cmd_show_set_raw_cmd_index, 10970 NULL, 10971 }, 10972 }; 10973 cmdline_parse_inst_t cmd_show_set_raw_all = { 10974 .f = cmd_show_set_raw_parsed, 10975 .data = NULL, 10976 .help_str = "show <raw_encap|raw_decap> all", 10977 .tokens = { 10978 (void *)&cmd_show_set_raw_cmd_show, 10979 (void *)&cmd_show_set_raw_cmd_what, 10980 (void *)&cmd_show_set_raw_cmd_all, 10981 NULL, 10982 }, 10983 }; 10984