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