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