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