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