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 HASH_CALC_ENCAP, 223 HASH_CALC_DEST, 224 ENCAP_HASH_FIELD_SRC_PORT, 225 ENCAP_HASH_FIELD_GRE_FLOW_ID, 226 227 /* Tunnel arguments. */ 228 TUNNEL_CREATE, 229 TUNNEL_CREATE_TYPE, 230 TUNNEL_LIST, 231 TUNNEL_DESTROY, 232 TUNNEL_DESTROY_ID, 233 234 /* Destroy arguments. */ 235 DESTROY_RULE, 236 DESTROY_IS_USER_ID, 237 238 /* Query arguments. */ 239 QUERY_ACTION, 240 QUERY_IS_USER_ID, 241 242 /* List arguments. */ 243 LIST_GROUP, 244 245 /* Destroy aged flow arguments. */ 246 AGED_DESTROY, 247 248 /* Validate/create arguments. */ 249 VC_GROUP, 250 VC_PRIORITY, 251 VC_INGRESS, 252 VC_EGRESS, 253 VC_TRANSFER, 254 VC_TUNNEL_SET, 255 VC_TUNNEL_MATCH, 256 VC_USER_ID, 257 258 /* Dump arguments */ 259 DUMP_ALL, 260 DUMP_ONE, 261 DUMP_IS_USER_ID, 262 263 /* Configure arguments */ 264 CONFIG_QUEUES_NUMBER, 265 CONFIG_QUEUES_SIZE, 266 CONFIG_COUNTERS_NUMBER, 267 CONFIG_AGING_OBJECTS_NUMBER, 268 CONFIG_METERS_NUMBER, 269 CONFIG_CONN_TRACK_NUMBER, 270 CONFIG_QUOTAS_NUMBER, 271 CONFIG_FLAGS, 272 CONFIG_HOST_PORT, 273 274 /* Indirect action arguments */ 275 INDIRECT_ACTION_CREATE, 276 INDIRECT_ACTION_LIST_CREATE, 277 INDIRECT_ACTION_FLOW_CONF_CREATE, 278 INDIRECT_ACTION_UPDATE, 279 INDIRECT_ACTION_DESTROY, 280 INDIRECT_ACTION_QUERY, 281 INDIRECT_ACTION_QUERY_UPDATE, 282 283 /* Indirect action create arguments */ 284 INDIRECT_ACTION_CREATE_ID, 285 INDIRECT_ACTION_INGRESS, 286 INDIRECT_ACTION_EGRESS, 287 INDIRECT_ACTION_TRANSFER, 288 INDIRECT_ACTION_SPEC, 289 INDIRECT_ACTION_LIST, 290 INDIRECT_ACTION_FLOW_CONF, 291 292 /* Indirect action destroy arguments */ 293 INDIRECT_ACTION_DESTROY_ID, 294 295 /* Indirect action query-and-update arguments */ 296 INDIRECT_ACTION_QU_MODE, 297 INDIRECT_ACTION_QU_MODE_NAME, 298 299 /* Validate/create pattern. */ 300 ITEM_PATTERN, 301 ITEM_PARAM_IS, 302 ITEM_PARAM_SPEC, 303 ITEM_PARAM_LAST, 304 ITEM_PARAM_MASK, 305 ITEM_PARAM_PREFIX, 306 ITEM_NEXT, 307 ITEM_END, 308 ITEM_VOID, 309 ITEM_INVERT, 310 ITEM_ANY, 311 ITEM_ANY_NUM, 312 ITEM_PORT_ID, 313 ITEM_PORT_ID_ID, 314 ITEM_MARK, 315 ITEM_MARK_ID, 316 ITEM_RAW, 317 ITEM_RAW_RELATIVE, 318 ITEM_RAW_SEARCH, 319 ITEM_RAW_OFFSET, 320 ITEM_RAW_LIMIT, 321 ITEM_RAW_PATTERN, 322 ITEM_RAW_PATTERN_HEX, 323 ITEM_ETH, 324 ITEM_ETH_DST, 325 ITEM_ETH_SRC, 326 ITEM_ETH_TYPE, 327 ITEM_ETH_HAS_VLAN, 328 ITEM_VLAN, 329 ITEM_VLAN_TCI, 330 ITEM_VLAN_PCP, 331 ITEM_VLAN_DEI, 332 ITEM_VLAN_VID, 333 ITEM_VLAN_INNER_TYPE, 334 ITEM_VLAN_HAS_MORE_VLAN, 335 ITEM_IPV4, 336 ITEM_IPV4_VER_IHL, 337 ITEM_IPV4_TOS, 338 ITEM_IPV4_LENGTH, 339 ITEM_IPV4_ID, 340 ITEM_IPV4_FRAGMENT_OFFSET, 341 ITEM_IPV4_TTL, 342 ITEM_IPV4_PROTO, 343 ITEM_IPV4_SRC, 344 ITEM_IPV4_DST, 345 ITEM_IPV6, 346 ITEM_IPV6_TC, 347 ITEM_IPV6_FLOW, 348 ITEM_IPV6_LEN, 349 ITEM_IPV6_PROTO, 350 ITEM_IPV6_HOP, 351 ITEM_IPV6_SRC, 352 ITEM_IPV6_DST, 353 ITEM_IPV6_HAS_FRAG_EXT, 354 ITEM_IPV6_ROUTING_EXT, 355 ITEM_IPV6_ROUTING_EXT_TYPE, 356 ITEM_IPV6_ROUTING_EXT_NEXT_HDR, 357 ITEM_IPV6_ROUTING_EXT_SEG_LEFT, 358 ITEM_ICMP, 359 ITEM_ICMP_TYPE, 360 ITEM_ICMP_CODE, 361 ITEM_ICMP_IDENT, 362 ITEM_ICMP_SEQ, 363 ITEM_UDP, 364 ITEM_UDP_SRC, 365 ITEM_UDP_DST, 366 ITEM_TCP, 367 ITEM_TCP_SRC, 368 ITEM_TCP_DST, 369 ITEM_TCP_FLAGS, 370 ITEM_SCTP, 371 ITEM_SCTP_SRC, 372 ITEM_SCTP_DST, 373 ITEM_SCTP_TAG, 374 ITEM_SCTP_CKSUM, 375 ITEM_VXLAN, 376 ITEM_VXLAN_VNI, 377 ITEM_VXLAN_LAST_RSVD, 378 ITEM_E_TAG, 379 ITEM_E_TAG_GRP_ECID_B, 380 ITEM_NVGRE, 381 ITEM_NVGRE_TNI, 382 ITEM_MPLS, 383 ITEM_MPLS_LABEL, 384 ITEM_MPLS_TC, 385 ITEM_MPLS_S, 386 ITEM_MPLS_TTL, 387 ITEM_GRE, 388 ITEM_GRE_PROTO, 389 ITEM_GRE_C_RSVD0_VER, 390 ITEM_GRE_C_BIT, 391 ITEM_GRE_K_BIT, 392 ITEM_GRE_S_BIT, 393 ITEM_FUZZY, 394 ITEM_FUZZY_THRESH, 395 ITEM_GTP, 396 ITEM_GTP_FLAGS, 397 ITEM_GTP_MSG_TYPE, 398 ITEM_GTP_TEID, 399 ITEM_GTPC, 400 ITEM_GTPU, 401 ITEM_GENEVE, 402 ITEM_GENEVE_VNI, 403 ITEM_GENEVE_PROTO, 404 ITEM_GENEVE_OPTLEN, 405 ITEM_VXLAN_GPE, 406 ITEM_VXLAN_GPE_VNI, 407 ITEM_VXLAN_GPE_PROTO, 408 ITEM_ARP_ETH_IPV4, 409 ITEM_ARP_ETH_IPV4_SHA, 410 ITEM_ARP_ETH_IPV4_SPA, 411 ITEM_ARP_ETH_IPV4_THA, 412 ITEM_ARP_ETH_IPV4_TPA, 413 ITEM_IPV6_EXT, 414 ITEM_IPV6_EXT_NEXT_HDR, 415 ITEM_IPV6_FRAG_EXT, 416 ITEM_IPV6_FRAG_EXT_NEXT_HDR, 417 ITEM_IPV6_FRAG_EXT_FRAG_DATA, 418 ITEM_IPV6_FRAG_EXT_ID, 419 ITEM_ICMP6, 420 ITEM_ICMP6_TYPE, 421 ITEM_ICMP6_CODE, 422 ITEM_ICMP6_ECHO_REQUEST, 423 ITEM_ICMP6_ECHO_REQUEST_ID, 424 ITEM_ICMP6_ECHO_REQUEST_SEQ, 425 ITEM_ICMP6_ECHO_REPLY, 426 ITEM_ICMP6_ECHO_REPLY_ID, 427 ITEM_ICMP6_ECHO_REPLY_SEQ, 428 ITEM_ICMP6_ND_NS, 429 ITEM_ICMP6_ND_NS_TARGET_ADDR, 430 ITEM_ICMP6_ND_NA, 431 ITEM_ICMP6_ND_NA_TARGET_ADDR, 432 ITEM_ICMP6_ND_OPT, 433 ITEM_ICMP6_ND_OPT_TYPE, 434 ITEM_ICMP6_ND_OPT_SLA_ETH, 435 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA, 436 ITEM_ICMP6_ND_OPT_TLA_ETH, 437 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA, 438 ITEM_META, 439 ITEM_META_DATA, 440 ITEM_RANDOM, 441 ITEM_RANDOM_VALUE, 442 ITEM_GRE_KEY, 443 ITEM_GRE_KEY_VALUE, 444 ITEM_GRE_OPTION, 445 ITEM_GRE_OPTION_CHECKSUM, 446 ITEM_GRE_OPTION_KEY, 447 ITEM_GRE_OPTION_SEQUENCE, 448 ITEM_GTP_PSC, 449 ITEM_GTP_PSC_QFI, 450 ITEM_GTP_PSC_PDU_T, 451 ITEM_PPPOES, 452 ITEM_PPPOED, 453 ITEM_PPPOE_SEID, 454 ITEM_PPPOE_PROTO_ID, 455 ITEM_HIGIG2, 456 ITEM_HIGIG2_CLASSIFICATION, 457 ITEM_HIGIG2_VID, 458 ITEM_TAG, 459 ITEM_TAG_DATA, 460 ITEM_TAG_INDEX, 461 ITEM_L2TPV3OIP, 462 ITEM_L2TPV3OIP_SESSION_ID, 463 ITEM_ESP, 464 ITEM_ESP_SPI, 465 ITEM_AH, 466 ITEM_AH_SPI, 467 ITEM_PFCP, 468 ITEM_PFCP_S_FIELD, 469 ITEM_PFCP_SEID, 470 ITEM_ECPRI, 471 ITEM_ECPRI_COMMON, 472 ITEM_ECPRI_COMMON_TYPE, 473 ITEM_ECPRI_COMMON_TYPE_IQ_DATA, 474 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL, 475 ITEM_ECPRI_COMMON_TYPE_DLY_MSR, 476 ITEM_ECPRI_MSG_IQ_DATA_PCID, 477 ITEM_ECPRI_MSG_RTC_CTRL_RTCID, 478 ITEM_ECPRI_MSG_DLY_MSR_MSRID, 479 ITEM_GENEVE_OPT, 480 ITEM_GENEVE_OPT_CLASS, 481 ITEM_GENEVE_OPT_TYPE, 482 ITEM_GENEVE_OPT_LENGTH, 483 ITEM_GENEVE_OPT_DATA, 484 ITEM_INTEGRITY, 485 ITEM_INTEGRITY_LEVEL, 486 ITEM_INTEGRITY_VALUE, 487 ITEM_CONNTRACK, 488 ITEM_POL_PORT, 489 ITEM_POL_METER, 490 ITEM_POL_POLICY, 491 ITEM_PORT_REPRESENTOR, 492 ITEM_PORT_REPRESENTOR_PORT_ID, 493 ITEM_REPRESENTED_PORT, 494 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID, 495 ITEM_FLEX, 496 ITEM_FLEX_ITEM_HANDLE, 497 ITEM_FLEX_PATTERN_HANDLE, 498 ITEM_L2TPV2, 499 ITEM_L2TPV2_TYPE, 500 ITEM_L2TPV2_TYPE_DATA, 501 ITEM_L2TPV2_TYPE_DATA_L, 502 ITEM_L2TPV2_TYPE_DATA_S, 503 ITEM_L2TPV2_TYPE_DATA_O, 504 ITEM_L2TPV2_TYPE_DATA_L_S, 505 ITEM_L2TPV2_TYPE_CTRL, 506 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID, 507 ITEM_L2TPV2_MSG_DATA_SESSION_ID, 508 ITEM_L2TPV2_MSG_DATA_L_LENGTH, 509 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID, 510 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID, 511 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID, 512 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID, 513 ITEM_L2TPV2_MSG_DATA_S_NS, 514 ITEM_L2TPV2_MSG_DATA_S_NR, 515 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID, 516 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID, 517 ITEM_L2TPV2_MSG_DATA_O_OFFSET, 518 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH, 519 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID, 520 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID, 521 ITEM_L2TPV2_MSG_DATA_L_S_NS, 522 ITEM_L2TPV2_MSG_DATA_L_S_NR, 523 ITEM_L2TPV2_MSG_CTRL_LENGTH, 524 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID, 525 ITEM_L2TPV2_MSG_CTRL_SESSION_ID, 526 ITEM_L2TPV2_MSG_CTRL_NS, 527 ITEM_L2TPV2_MSG_CTRL_NR, 528 ITEM_PPP, 529 ITEM_PPP_ADDR, 530 ITEM_PPP_CTRL, 531 ITEM_PPP_PROTO_ID, 532 ITEM_METER, 533 ITEM_METER_COLOR, 534 ITEM_METER_COLOR_NAME, 535 ITEM_QUOTA, 536 ITEM_QUOTA_STATE, 537 ITEM_QUOTA_STATE_NAME, 538 ITEM_AGGR_AFFINITY, 539 ITEM_AGGR_AFFINITY_VALUE, 540 ITEM_TX_QUEUE, 541 ITEM_TX_QUEUE_VALUE, 542 ITEM_IB_BTH, 543 ITEM_IB_BTH_OPCODE, 544 ITEM_IB_BTH_PKEY, 545 ITEM_IB_BTH_DST_QPN, 546 ITEM_IB_BTH_PSN, 547 ITEM_IPV6_PUSH_REMOVE_EXT, 548 ITEM_IPV6_PUSH_REMOVE_EXT_TYPE, 549 ITEM_PTYPE, 550 ITEM_PTYPE_VALUE, 551 ITEM_NSH, 552 ITEM_COMPARE, 553 ITEM_COMPARE_OP, 554 ITEM_COMPARE_OP_VALUE, 555 ITEM_COMPARE_FIELD_A_TYPE, 556 ITEM_COMPARE_FIELD_A_TYPE_VALUE, 557 ITEM_COMPARE_FIELD_A_LEVEL, 558 ITEM_COMPARE_FIELD_A_LEVEL_VALUE, 559 ITEM_COMPARE_FIELD_A_TAG_INDEX, 560 ITEM_COMPARE_FIELD_A_TYPE_ID, 561 ITEM_COMPARE_FIELD_A_CLASS_ID, 562 ITEM_COMPARE_FIELD_A_OFFSET, 563 ITEM_COMPARE_FIELD_B_TYPE, 564 ITEM_COMPARE_FIELD_B_TYPE_VALUE, 565 ITEM_COMPARE_FIELD_B_LEVEL, 566 ITEM_COMPARE_FIELD_B_LEVEL_VALUE, 567 ITEM_COMPARE_FIELD_B_TAG_INDEX, 568 ITEM_COMPARE_FIELD_B_TYPE_ID, 569 ITEM_COMPARE_FIELD_B_CLASS_ID, 570 ITEM_COMPARE_FIELD_B_OFFSET, 571 ITEM_COMPARE_FIELD_B_VALUE, 572 ITEM_COMPARE_FIELD_B_POINTER, 573 ITEM_COMPARE_FIELD_WIDTH, 574 575 /* Validate/create actions. */ 576 ACTIONS, 577 ACTION_NEXT, 578 ACTION_END, 579 ACTION_VOID, 580 ACTION_PASSTHRU, 581 ACTION_SKIP_CMAN, 582 ACTION_JUMP, 583 ACTION_JUMP_GROUP, 584 ACTION_MARK, 585 ACTION_MARK_ID, 586 ACTION_FLAG, 587 ACTION_QUEUE, 588 ACTION_QUEUE_INDEX, 589 ACTION_DROP, 590 ACTION_COUNT, 591 ACTION_COUNT_ID, 592 ACTION_RSS, 593 ACTION_RSS_FUNC, 594 ACTION_RSS_LEVEL, 595 ACTION_RSS_FUNC_DEFAULT, 596 ACTION_RSS_FUNC_TOEPLITZ, 597 ACTION_RSS_FUNC_SIMPLE_XOR, 598 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ, 599 ACTION_RSS_TYPES, 600 ACTION_RSS_TYPE, 601 ACTION_RSS_KEY, 602 ACTION_RSS_KEY_LEN, 603 ACTION_RSS_QUEUES, 604 ACTION_RSS_QUEUE, 605 ACTION_PF, 606 ACTION_VF, 607 ACTION_VF_ORIGINAL, 608 ACTION_VF_ID, 609 ACTION_PORT_ID, 610 ACTION_PORT_ID_ORIGINAL, 611 ACTION_PORT_ID_ID, 612 ACTION_METER, 613 ACTION_METER_COLOR, 614 ACTION_METER_COLOR_TYPE, 615 ACTION_METER_COLOR_GREEN, 616 ACTION_METER_COLOR_YELLOW, 617 ACTION_METER_COLOR_RED, 618 ACTION_METER_ID, 619 ACTION_METER_MARK, 620 ACTION_METER_PROFILE, 621 ACTION_METER_PROFILE_ID2PTR, 622 ACTION_METER_POLICY, 623 ACTION_METER_POLICY_ID2PTR, 624 ACTION_METER_COLOR_MODE, 625 ACTION_METER_STATE, 626 ACTION_OF_DEC_NW_TTL, 627 ACTION_OF_POP_VLAN, 628 ACTION_OF_PUSH_VLAN, 629 ACTION_OF_PUSH_VLAN_ETHERTYPE, 630 ACTION_OF_SET_VLAN_VID, 631 ACTION_OF_SET_VLAN_VID_VLAN_VID, 632 ACTION_OF_SET_VLAN_PCP, 633 ACTION_OF_SET_VLAN_PCP_VLAN_PCP, 634 ACTION_OF_POP_MPLS, 635 ACTION_OF_POP_MPLS_ETHERTYPE, 636 ACTION_OF_PUSH_MPLS, 637 ACTION_OF_PUSH_MPLS_ETHERTYPE, 638 ACTION_VXLAN_ENCAP, 639 ACTION_VXLAN_DECAP, 640 ACTION_NVGRE_ENCAP, 641 ACTION_NVGRE_DECAP, 642 ACTION_L2_ENCAP, 643 ACTION_L2_DECAP, 644 ACTION_MPLSOGRE_ENCAP, 645 ACTION_MPLSOGRE_DECAP, 646 ACTION_MPLSOUDP_ENCAP, 647 ACTION_MPLSOUDP_DECAP, 648 ACTION_SET_IPV4_SRC, 649 ACTION_SET_IPV4_SRC_IPV4_SRC, 650 ACTION_SET_IPV4_DST, 651 ACTION_SET_IPV4_DST_IPV4_DST, 652 ACTION_SET_IPV6_SRC, 653 ACTION_SET_IPV6_SRC_IPV6_SRC, 654 ACTION_SET_IPV6_DST, 655 ACTION_SET_IPV6_DST_IPV6_DST, 656 ACTION_SET_TP_SRC, 657 ACTION_SET_TP_SRC_TP_SRC, 658 ACTION_SET_TP_DST, 659 ACTION_SET_TP_DST_TP_DST, 660 ACTION_MAC_SWAP, 661 ACTION_DEC_TTL, 662 ACTION_SET_TTL, 663 ACTION_SET_TTL_TTL, 664 ACTION_SET_MAC_SRC, 665 ACTION_SET_MAC_SRC_MAC_SRC, 666 ACTION_SET_MAC_DST, 667 ACTION_SET_MAC_DST_MAC_DST, 668 ACTION_INC_TCP_SEQ, 669 ACTION_INC_TCP_SEQ_VALUE, 670 ACTION_DEC_TCP_SEQ, 671 ACTION_DEC_TCP_SEQ_VALUE, 672 ACTION_INC_TCP_ACK, 673 ACTION_INC_TCP_ACK_VALUE, 674 ACTION_DEC_TCP_ACK, 675 ACTION_DEC_TCP_ACK_VALUE, 676 ACTION_RAW_ENCAP, 677 ACTION_RAW_DECAP, 678 ACTION_RAW_ENCAP_SIZE, 679 ACTION_RAW_ENCAP_INDEX, 680 ACTION_RAW_ENCAP_INDEX_VALUE, 681 ACTION_RAW_DECAP_INDEX, 682 ACTION_RAW_DECAP_INDEX_VALUE, 683 ACTION_SET_TAG, 684 ACTION_SET_TAG_DATA, 685 ACTION_SET_TAG_INDEX, 686 ACTION_SET_TAG_MASK, 687 ACTION_SET_META, 688 ACTION_SET_META_DATA, 689 ACTION_SET_META_MASK, 690 ACTION_SET_IPV4_DSCP, 691 ACTION_SET_IPV4_DSCP_VALUE, 692 ACTION_SET_IPV6_DSCP, 693 ACTION_SET_IPV6_DSCP_VALUE, 694 ACTION_AGE, 695 ACTION_AGE_TIMEOUT, 696 ACTION_AGE_UPDATE, 697 ACTION_AGE_UPDATE_TIMEOUT, 698 ACTION_AGE_UPDATE_TOUCH, 699 ACTION_SAMPLE, 700 ACTION_SAMPLE_RATIO, 701 ACTION_SAMPLE_INDEX, 702 ACTION_SAMPLE_INDEX_VALUE, 703 ACTION_INDIRECT, 704 ACTION_INDIRECT_LIST, 705 ACTION_INDIRECT_LIST_HANDLE, 706 ACTION_INDIRECT_LIST_CONF, 707 INDIRECT_LIST_ACTION_ID2PTR_HANDLE, 708 INDIRECT_LIST_ACTION_ID2PTR_CONF, 709 ACTION_SHARED_INDIRECT, 710 INDIRECT_ACTION_PORT, 711 INDIRECT_ACTION_ID2PTR, 712 ACTION_MODIFY_FIELD, 713 ACTION_MODIFY_FIELD_OP, 714 ACTION_MODIFY_FIELD_OP_VALUE, 715 ACTION_MODIFY_FIELD_DST_TYPE, 716 ACTION_MODIFY_FIELD_DST_TYPE_VALUE, 717 ACTION_MODIFY_FIELD_DST_LEVEL, 718 ACTION_MODIFY_FIELD_DST_LEVEL_VALUE, 719 ACTION_MODIFY_FIELD_DST_TAG_INDEX, 720 ACTION_MODIFY_FIELD_DST_TYPE_ID, 721 ACTION_MODIFY_FIELD_DST_CLASS_ID, 722 ACTION_MODIFY_FIELD_DST_OFFSET, 723 ACTION_MODIFY_FIELD_SRC_TYPE, 724 ACTION_MODIFY_FIELD_SRC_TYPE_VALUE, 725 ACTION_MODIFY_FIELD_SRC_LEVEL, 726 ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE, 727 ACTION_MODIFY_FIELD_SRC_TAG_INDEX, 728 ACTION_MODIFY_FIELD_SRC_TYPE_ID, 729 ACTION_MODIFY_FIELD_SRC_CLASS_ID, 730 ACTION_MODIFY_FIELD_SRC_OFFSET, 731 ACTION_MODIFY_FIELD_SRC_VALUE, 732 ACTION_MODIFY_FIELD_SRC_POINTER, 733 ACTION_MODIFY_FIELD_WIDTH, 734 ACTION_CONNTRACK, 735 ACTION_CONNTRACK_UPDATE, 736 ACTION_CONNTRACK_UPDATE_DIR, 737 ACTION_CONNTRACK_UPDATE_CTX, 738 ACTION_POL_G, 739 ACTION_POL_Y, 740 ACTION_POL_R, 741 ACTION_PORT_REPRESENTOR, 742 ACTION_PORT_REPRESENTOR_PORT_ID, 743 ACTION_REPRESENTED_PORT, 744 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID, 745 ACTION_SEND_TO_KERNEL, 746 ACTION_QUOTA_CREATE, 747 ACTION_QUOTA_CREATE_LIMIT, 748 ACTION_QUOTA_CREATE_MODE, 749 ACTION_QUOTA_CREATE_MODE_NAME, 750 ACTION_QUOTA_QU, 751 ACTION_QUOTA_QU_LIMIT, 752 ACTION_QUOTA_QU_UPDATE_OP, 753 ACTION_QUOTA_QU_UPDATE_OP_NAME, 754 ACTION_IPV6_EXT_REMOVE, 755 ACTION_IPV6_EXT_REMOVE_INDEX, 756 ACTION_IPV6_EXT_REMOVE_INDEX_VALUE, 757 ACTION_IPV6_EXT_PUSH, 758 ACTION_IPV6_EXT_PUSH_INDEX, 759 ACTION_IPV6_EXT_PUSH_INDEX_VALUE, 760 ACTION_NAT64, 761 ACTION_NAT64_MODE, 762 }; 763 764 /** Maximum size for pattern in struct rte_flow_item_raw. */ 765 #define ITEM_RAW_PATTERN_SIZE 512 766 767 /** Maximum size for GENEVE option data pattern in bytes. */ 768 #define ITEM_GENEVE_OPT_DATA_SIZE 124 769 770 /** Storage size for struct rte_flow_item_raw including pattern. */ 771 #define ITEM_RAW_SIZE \ 772 (sizeof(struct rte_flow_item_raw) + ITEM_RAW_PATTERN_SIZE) 773 774 static const char *const compare_ops[] = { 775 "eq", "ne", "lt", "le", "gt", "ge", NULL 776 }; 777 778 /** Maximum size for external pattern in struct rte_flow_field_data. */ 779 #define FLOW_FIELD_PATTERN_SIZE 32 780 781 /** Storage size for struct rte_flow_action_modify_field including pattern. */ 782 #define ACTION_MODIFY_SIZE \ 783 (sizeof(struct rte_flow_action_modify_field) + \ 784 FLOW_FIELD_PATTERN_SIZE) 785 786 /** Maximum number of queue indices in struct rte_flow_action_rss. */ 787 #define ACTION_RSS_QUEUE_NUM 128 788 789 /** Storage for struct rte_flow_action_rss including external data. */ 790 struct action_rss_data { 791 struct rte_flow_action_rss conf; 792 uint8_t key[RSS_HASH_KEY_LENGTH]; 793 uint16_t queue[ACTION_RSS_QUEUE_NUM]; 794 }; 795 796 /** Maximum data size in struct rte_flow_action_raw_encap. */ 797 #define ACTION_RAW_ENCAP_MAX_DATA 512 798 #define RAW_ENCAP_CONFS_MAX_NUM 8 799 800 /** Storage for struct rte_flow_action_raw_encap. */ 801 struct raw_encap_conf { 802 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA]; 803 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA]; 804 size_t size; 805 }; 806 807 struct raw_encap_conf raw_encap_confs[RAW_ENCAP_CONFS_MAX_NUM]; 808 809 /** Storage for struct rte_flow_action_raw_encap including external data. */ 810 struct action_raw_encap_data { 811 struct rte_flow_action_raw_encap conf; 812 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA]; 813 uint8_t preserve[ACTION_RAW_ENCAP_MAX_DATA]; 814 uint16_t idx; 815 }; 816 817 /** Storage for struct rte_flow_action_raw_decap. */ 818 struct raw_decap_conf { 819 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA]; 820 size_t size; 821 }; 822 823 struct raw_decap_conf raw_decap_confs[RAW_ENCAP_CONFS_MAX_NUM]; 824 825 /** Storage for struct rte_flow_action_raw_decap including external data. */ 826 struct action_raw_decap_data { 827 struct rte_flow_action_raw_decap conf; 828 uint8_t data[ACTION_RAW_ENCAP_MAX_DATA]; 829 uint16_t idx; 830 }; 831 832 /** Maximum data size in struct rte_flow_action_ipv6_ext_push. */ 833 #define ACTION_IPV6_EXT_PUSH_MAX_DATA 512 834 #define IPV6_EXT_PUSH_CONFS_MAX_NUM 8 835 836 /** Storage for struct rte_flow_action_ipv6_ext_push. */ 837 struct ipv6_ext_push_conf { 838 uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA]; 839 size_t size; 840 uint8_t type; 841 }; 842 843 struct ipv6_ext_push_conf ipv6_ext_push_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM]; 844 845 /** Storage for struct rte_flow_action_ipv6_ext_push including external data. */ 846 struct action_ipv6_ext_push_data { 847 struct rte_flow_action_ipv6_ext_push conf; 848 uint8_t data[ACTION_IPV6_EXT_PUSH_MAX_DATA]; 849 uint8_t type; 850 uint16_t idx; 851 }; 852 853 /** Storage for struct rte_flow_action_ipv6_ext_remove. */ 854 struct ipv6_ext_remove_conf { 855 struct rte_flow_action_ipv6_ext_remove conf; 856 uint8_t type; 857 }; 858 859 struct ipv6_ext_remove_conf ipv6_ext_remove_confs[IPV6_EXT_PUSH_CONFS_MAX_NUM]; 860 861 /** Storage for struct rte_flow_action_ipv6_ext_remove including external data. */ 862 struct action_ipv6_ext_remove_data { 863 struct rte_flow_action_ipv6_ext_remove conf; 864 uint8_t type; 865 uint16_t idx; 866 }; 867 868 struct vxlan_encap_conf vxlan_encap_conf = { 869 .select_ipv4 = 1, 870 .select_vlan = 0, 871 .select_tos_ttl = 0, 872 .vni = "\x00\x00\x00", 873 .udp_src = 0, 874 .udp_dst = RTE_BE16(RTE_VXLAN_DEFAULT_PORT), 875 .ipv4_src = RTE_IPV4(127, 0, 0, 1), 876 .ipv4_dst = RTE_IPV4(255, 255, 255, 255), 877 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00" 878 "\x00\x00\x00\x00\x00\x00\x00\x01", 879 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00" 880 "\x00\x00\x00\x00\x00\x00\x11\x11", 881 .vlan_tci = 0, 882 .ip_tos = 0, 883 .ip_ttl = 255, 884 .eth_src = "\x00\x00\x00\x00\x00\x00", 885 .eth_dst = "\xff\xff\xff\xff\xff\xff", 886 }; 887 888 /** Maximum number of items in struct rte_flow_action_vxlan_encap. */ 889 #define ACTION_VXLAN_ENCAP_ITEMS_NUM 6 890 891 /** Storage for struct rte_flow_action_vxlan_encap including external data. */ 892 struct action_vxlan_encap_data { 893 struct rte_flow_action_vxlan_encap conf; 894 struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM]; 895 struct rte_flow_item_eth item_eth; 896 struct rte_flow_item_vlan item_vlan; 897 union { 898 struct rte_flow_item_ipv4 item_ipv4; 899 struct rte_flow_item_ipv6 item_ipv6; 900 }; 901 struct rte_flow_item_udp item_udp; 902 struct rte_flow_item_vxlan item_vxlan; 903 }; 904 905 struct nvgre_encap_conf nvgre_encap_conf = { 906 .select_ipv4 = 1, 907 .select_vlan = 0, 908 .tni = "\x00\x00\x00", 909 .ipv4_src = RTE_IPV4(127, 0, 0, 1), 910 .ipv4_dst = RTE_IPV4(255, 255, 255, 255), 911 .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00" 912 "\x00\x00\x00\x00\x00\x00\x00\x01", 913 .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00" 914 "\x00\x00\x00\x00\x00\x00\x11\x11", 915 .vlan_tci = 0, 916 .eth_src = "\x00\x00\x00\x00\x00\x00", 917 .eth_dst = "\xff\xff\xff\xff\xff\xff", 918 }; 919 920 /** Maximum number of items in struct rte_flow_action_nvgre_encap. */ 921 #define ACTION_NVGRE_ENCAP_ITEMS_NUM 5 922 923 /** Storage for struct rte_flow_action_nvgre_encap including external data. */ 924 struct action_nvgre_encap_data { 925 struct rte_flow_action_nvgre_encap conf; 926 struct rte_flow_item items[ACTION_NVGRE_ENCAP_ITEMS_NUM]; 927 struct rte_flow_item_eth item_eth; 928 struct rte_flow_item_vlan item_vlan; 929 union { 930 struct rte_flow_item_ipv4 item_ipv4; 931 struct rte_flow_item_ipv6 item_ipv6; 932 }; 933 struct rte_flow_item_nvgre item_nvgre; 934 }; 935 936 struct l2_encap_conf l2_encap_conf; 937 938 struct l2_decap_conf l2_decap_conf; 939 940 struct mplsogre_encap_conf mplsogre_encap_conf; 941 942 struct mplsogre_decap_conf mplsogre_decap_conf; 943 944 struct mplsoudp_encap_conf mplsoudp_encap_conf; 945 946 struct mplsoudp_decap_conf mplsoudp_decap_conf; 947 948 struct rte_flow_action_conntrack conntrack_context; 949 950 #define ACTION_SAMPLE_ACTIONS_NUM 10 951 #define RAW_SAMPLE_CONFS_MAX_NUM 8 952 /** Storage for struct rte_flow_action_sample including external data. */ 953 struct action_sample_data { 954 struct rte_flow_action_sample conf; 955 uint32_t idx; 956 }; 957 /** Storage for struct rte_flow_action_sample. */ 958 struct raw_sample_conf { 959 struct rte_flow_action data[ACTION_SAMPLE_ACTIONS_NUM]; 960 }; 961 struct raw_sample_conf raw_sample_confs[RAW_SAMPLE_CONFS_MAX_NUM]; 962 struct rte_flow_action_mark sample_mark[RAW_SAMPLE_CONFS_MAX_NUM]; 963 struct rte_flow_action_queue sample_queue[RAW_SAMPLE_CONFS_MAX_NUM]; 964 struct rte_flow_action_count sample_count[RAW_SAMPLE_CONFS_MAX_NUM]; 965 struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM]; 966 struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM]; 967 struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM]; 968 struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM]; 969 struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM]; 970 struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM]; 971 struct rte_flow_action_ethdev sample_port_representor[RAW_SAMPLE_CONFS_MAX_NUM]; 972 struct rte_flow_action_ethdev sample_represented_port[RAW_SAMPLE_CONFS_MAX_NUM]; 973 974 static const char *const modify_field_ops[] = { 975 "set", "add", "sub", NULL 976 }; 977 978 static const char *const flow_field_ids[] = { 979 "start", "mac_dst", "mac_src", 980 "vlan_type", "vlan_id", "mac_type", 981 "ipv4_dscp", "ipv4_ttl", "ipv4_src", "ipv4_dst", 982 "ipv6_dscp", "ipv6_hoplimit", "ipv6_src", "ipv6_dst", 983 "tcp_port_src", "tcp_port_dst", 984 "tcp_seq_num", "tcp_ack_num", "tcp_flags", 985 "udp_port_src", "udp_port_dst", 986 "vxlan_vni", "geneve_vni", "gtp_teid", 987 "tag", "mark", "meta", "pointer", "value", 988 "ipv4_ecn", "ipv6_ecn", "gtp_psc_qfi", "meter_color", 989 "ipv6_proto", 990 "flex_item", 991 "hash_result", 992 "geneve_opt_type", "geneve_opt_class", "geneve_opt_data", "mpls", 993 "tcp_data_off", "ipv4_ihl", "ipv4_total_len", "ipv6_payload_len", 994 "random", 995 NULL 996 }; 997 998 static const char *const meter_colors[] = { 999 "green", "yellow", "red", "all", NULL 1000 }; 1001 1002 static const char *const table_insertion_types[] = { 1003 "pattern", "index", NULL 1004 }; 1005 1006 static const char *const table_hash_funcs[] = { 1007 "default", "linear", "crc32", "crc16", NULL 1008 }; 1009 1010 #define RAW_IPSEC_CONFS_MAX_NUM 8 1011 1012 /** Maximum number of subsequent tokens and arguments on the stack. */ 1013 #define CTX_STACK_SIZE 16 1014 1015 /** Parser context. */ 1016 struct context { 1017 /** Stack of subsequent token lists to process. */ 1018 const enum index *next[CTX_STACK_SIZE]; 1019 /** Arguments for stacked tokens. */ 1020 const void *args[CTX_STACK_SIZE]; 1021 enum index curr; /**< Current token index. */ 1022 enum index prev; /**< Index of the last token seen. */ 1023 int next_num; /**< Number of entries in next[]. */ 1024 int args_num; /**< Number of entries in args[]. */ 1025 uint32_t eol:1; /**< EOL has been detected. */ 1026 uint32_t last:1; /**< No more arguments. */ 1027 portid_t port; /**< Current port ID (for completions). */ 1028 uint32_t objdata; /**< Object-specific data. */ 1029 void *object; /**< Address of current object for relative offsets. */ 1030 void *objmask; /**< Object a full mask must be written to. */ 1031 }; 1032 1033 /** Token argument. */ 1034 struct arg { 1035 uint32_t hton:1; /**< Use network byte ordering. */ 1036 uint32_t sign:1; /**< Value is signed. */ 1037 uint32_t bounded:1; /**< Value is bounded. */ 1038 uintmax_t min; /**< Minimum value if bounded. */ 1039 uintmax_t max; /**< Maximum value if bounded. */ 1040 uint32_t offset; /**< Relative offset from ctx->object. */ 1041 uint32_t size; /**< Field size. */ 1042 const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */ 1043 }; 1044 1045 /** Parser token definition. */ 1046 struct token { 1047 /** Type displayed during completion (defaults to "TOKEN"). */ 1048 const char *type; 1049 /** Help displayed during completion (defaults to token name). */ 1050 const char *help; 1051 /** Private data used by parser functions. */ 1052 const void *priv; 1053 /** 1054 * Lists of subsequent tokens to push on the stack. Each call to the 1055 * parser consumes the last entry of that stack. 1056 */ 1057 const enum index *const *next; 1058 /** Arguments stack for subsequent tokens that need them. */ 1059 const struct arg *const *args; 1060 /** 1061 * Token-processing callback, returns -1 in case of error, the 1062 * length of the matched string otherwise. If NULL, attempts to 1063 * match the token name. 1064 * 1065 * If buf is not NULL, the result should be stored in it according 1066 * to context. An error is returned if not large enough. 1067 */ 1068 int (*call)(struct context *ctx, const struct token *token, 1069 const char *str, unsigned int len, 1070 void *buf, unsigned int size); 1071 /** 1072 * Callback that provides possible values for this token, used for 1073 * completion. Returns -1 in case of error, the number of possible 1074 * values otherwise. If NULL, the token name is used. 1075 * 1076 * If buf is not NULL, entry index ent is written to buf and the 1077 * full length of the entry is returned (same behavior as 1078 * snprintf()). 1079 */ 1080 int (*comp)(struct context *ctx, const struct token *token, 1081 unsigned int ent, char *buf, unsigned int size); 1082 /** Mandatory token name, no default value. */ 1083 const char *name; 1084 }; 1085 1086 /** Static initializer for the next field. */ 1087 #define NEXT(...) (const enum index *const []){ __VA_ARGS__, NULL, } 1088 1089 /** Static initializer for a NEXT() entry. */ 1090 #define NEXT_ENTRY(...) (const enum index []){ __VA_ARGS__, ZERO, } 1091 1092 /** Static initializer for the args field. */ 1093 #define ARGS(...) (const struct arg *const []){ __VA_ARGS__, NULL, } 1094 1095 /** Static initializer for ARGS() to target a field. */ 1096 #define ARGS_ENTRY(s, f) \ 1097 (&(const struct arg){ \ 1098 .offset = offsetof(s, f), \ 1099 .size = sizeof(((s *)0)->f), \ 1100 }) 1101 1102 /** Static initializer for ARGS() to target a bit-field. */ 1103 #define ARGS_ENTRY_BF(s, f, b) \ 1104 (&(const struct arg){ \ 1105 .size = sizeof(s), \ 1106 .mask = (const void *)&(const s){ .f = (1 << (b)) - 1 }, \ 1107 }) 1108 1109 /** Static initializer for ARGS() to target a field with limits. */ 1110 #define ARGS_ENTRY_BOUNDED(s, f, i, a) \ 1111 (&(const struct arg){ \ 1112 .bounded = 1, \ 1113 .min = (i), \ 1114 .max = (a), \ 1115 .offset = offsetof(s, f), \ 1116 .size = sizeof(((s *)0)->f), \ 1117 }) 1118 1119 /** Static initializer for ARGS() to target an arbitrary bit-mask. */ 1120 #define ARGS_ENTRY_MASK(s, f, m) \ 1121 (&(const struct arg){ \ 1122 .offset = offsetof(s, f), \ 1123 .size = sizeof(((s *)0)->f), \ 1124 .mask = (const void *)(m), \ 1125 }) 1126 1127 /** Same as ARGS_ENTRY_MASK() using network byte ordering for the value. */ 1128 #define ARGS_ENTRY_MASK_HTON(s, f, m) \ 1129 (&(const struct arg){ \ 1130 .hton = 1, \ 1131 .offset = offsetof(s, f), \ 1132 .size = sizeof(((s *)0)->f), \ 1133 .mask = (const void *)(m), \ 1134 }) 1135 1136 /** Static initializer for ARGS() to target a pointer. */ 1137 #define ARGS_ENTRY_PTR(s, f) \ 1138 (&(const struct arg){ \ 1139 .size = sizeof(*((s *)0)->f), \ 1140 }) 1141 1142 /** Static initializer for ARGS() with arbitrary offset and size. */ 1143 #define ARGS_ENTRY_ARB(o, s) \ 1144 (&(const struct arg){ \ 1145 .offset = (o), \ 1146 .size = (s), \ 1147 }) 1148 1149 /** Same as ARGS_ENTRY_ARB() with bounded values. */ 1150 #define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \ 1151 (&(const struct arg){ \ 1152 .bounded = 1, \ 1153 .min = (i), \ 1154 .max = (a), \ 1155 .offset = (o), \ 1156 .size = (s), \ 1157 }) 1158 1159 /** Same as ARGS_ENTRY() using network byte ordering. */ 1160 #define ARGS_ENTRY_HTON(s, f) \ 1161 (&(const struct arg){ \ 1162 .hton = 1, \ 1163 .offset = offsetof(s, f), \ 1164 .size = sizeof(((s *)0)->f), \ 1165 }) 1166 1167 /** Same as ARGS_ENTRY_HTON() for a single argument, without structure. */ 1168 #define ARG_ENTRY_HTON(s) \ 1169 (&(const struct arg){ \ 1170 .hton = 1, \ 1171 .offset = 0, \ 1172 .size = sizeof(s), \ 1173 }) 1174 1175 /** Parser output buffer layout expected by cmd_flow_parsed(). */ 1176 struct buffer { 1177 enum index command; /**< Flow command. */ 1178 portid_t port; /**< Affected port ID. */ 1179 queueid_t queue; /** Async queue ID. */ 1180 bool postpone; /** Postpone async operation */ 1181 union { 1182 struct { 1183 struct rte_flow_port_attr port_attr; 1184 uint32_t nb_queue; 1185 struct rte_flow_queue_attr queue_attr; 1186 } configure; /**< Configuration arguments. */ 1187 struct { 1188 uint32_t *template_id; 1189 uint32_t template_id_n; 1190 } templ_destroy; /**< Template destroy arguments. */ 1191 struct { 1192 uint32_t id; 1193 struct rte_flow_template_table_attr attr; 1194 uint32_t *pat_templ_id; 1195 uint32_t pat_templ_id_n; 1196 uint32_t *act_templ_id; 1197 uint32_t act_templ_id_n; 1198 } table; /**< Table arguments. */ 1199 struct { 1200 uint32_t *table_id; 1201 uint32_t table_id_n; 1202 } table_destroy; /**< Template destroy arguments. */ 1203 struct { 1204 uint32_t *action_id; 1205 uint32_t action_id_n; 1206 } ia_destroy; /**< Indirect action destroy arguments. */ 1207 struct { 1208 uint32_t action_id; 1209 enum rte_flow_query_update_mode qu_mode; 1210 } ia; /* Indirect action query arguments */ 1211 struct { 1212 uint32_t table_id; 1213 uint32_t pat_templ_id; 1214 uint32_t rule_id; 1215 uint32_t act_templ_id; 1216 struct rte_flow_attr attr; 1217 struct tunnel_ops tunnel_ops; 1218 uintptr_t user_id; 1219 struct rte_flow_item *pattern; 1220 struct rte_flow_action *actions; 1221 struct rte_flow_action *masks; 1222 uint32_t pattern_n; 1223 uint32_t actions_n; 1224 uint8_t *data; 1225 enum rte_flow_encap_hash_field field; 1226 uint8_t encap_hash; 1227 } vc; /**< Validate/create arguments. */ 1228 struct { 1229 uint64_t *rule; 1230 uint64_t rule_n; 1231 bool is_user_id; 1232 } destroy; /**< Destroy arguments. */ 1233 struct { 1234 char file[128]; 1235 bool mode; 1236 uint64_t rule; 1237 bool is_user_id; 1238 } dump; /**< Dump arguments. */ 1239 struct { 1240 uint64_t rule; 1241 struct rte_flow_action action; 1242 bool is_user_id; 1243 } query; /**< Query arguments. */ 1244 struct { 1245 uint32_t *group; 1246 uint32_t group_n; 1247 } list; /**< List arguments. */ 1248 struct { 1249 int set; 1250 } isolate; /**< Isolated mode arguments. */ 1251 struct { 1252 int destroy; 1253 } aged; /**< Aged arguments. */ 1254 struct { 1255 uint32_t policy_id; 1256 } policy;/**< Policy arguments. */ 1257 struct { 1258 uint16_t token; 1259 uintptr_t uintptr; 1260 char filename[128]; 1261 } flex; /**< Flex arguments*/ 1262 } args; /**< Command arguments. */ 1263 }; 1264 1265 /** Private data for pattern items. */ 1266 struct parse_item_priv { 1267 enum rte_flow_item_type type; /**< Item type. */ 1268 uint32_t size; /**< Size of item specification structure. */ 1269 }; 1270 1271 #define PRIV_ITEM(t, s) \ 1272 (&(const struct parse_item_priv){ \ 1273 .type = RTE_FLOW_ITEM_TYPE_ ## t, \ 1274 .size = s, \ 1275 }) 1276 1277 /** Private data for actions. */ 1278 struct parse_action_priv { 1279 enum rte_flow_action_type type; /**< Action type. */ 1280 uint32_t size; /**< Size of action configuration structure. */ 1281 }; 1282 1283 #define PRIV_ACTION(t, s) \ 1284 (&(const struct parse_action_priv){ \ 1285 .type = RTE_FLOW_ACTION_TYPE_ ## t, \ 1286 .size = s, \ 1287 }) 1288 1289 static const enum index next_flex_item[] = { 1290 FLEX_ITEM_INIT, 1291 FLEX_ITEM_CREATE, 1292 FLEX_ITEM_DESTROY, 1293 ZERO, 1294 }; 1295 1296 static const enum index next_config_attr[] = { 1297 CONFIG_QUEUES_NUMBER, 1298 CONFIG_QUEUES_SIZE, 1299 CONFIG_COUNTERS_NUMBER, 1300 CONFIG_AGING_OBJECTS_NUMBER, 1301 CONFIG_METERS_NUMBER, 1302 CONFIG_CONN_TRACK_NUMBER, 1303 CONFIG_QUOTAS_NUMBER, 1304 CONFIG_FLAGS, 1305 CONFIG_HOST_PORT, 1306 END, 1307 ZERO, 1308 }; 1309 1310 static const enum index next_pt_subcmd[] = { 1311 PATTERN_TEMPLATE_CREATE, 1312 PATTERN_TEMPLATE_DESTROY, 1313 ZERO, 1314 }; 1315 1316 static const enum index next_pt_attr[] = { 1317 PATTERN_TEMPLATE_CREATE_ID, 1318 PATTERN_TEMPLATE_RELAXED_MATCHING, 1319 PATTERN_TEMPLATE_INGRESS, 1320 PATTERN_TEMPLATE_EGRESS, 1321 PATTERN_TEMPLATE_TRANSFER, 1322 PATTERN_TEMPLATE_SPEC, 1323 ZERO, 1324 }; 1325 1326 static const enum index next_pt_destroy_attr[] = { 1327 PATTERN_TEMPLATE_DESTROY_ID, 1328 END, 1329 ZERO, 1330 }; 1331 1332 static const enum index next_at_subcmd[] = { 1333 ACTIONS_TEMPLATE_CREATE, 1334 ACTIONS_TEMPLATE_DESTROY, 1335 ZERO, 1336 }; 1337 1338 static const enum index next_at_attr[] = { 1339 ACTIONS_TEMPLATE_CREATE_ID, 1340 ACTIONS_TEMPLATE_INGRESS, 1341 ACTIONS_TEMPLATE_EGRESS, 1342 ACTIONS_TEMPLATE_TRANSFER, 1343 ACTIONS_TEMPLATE_SPEC, 1344 ZERO, 1345 }; 1346 1347 static const enum index next_at_destroy_attr[] = { 1348 ACTIONS_TEMPLATE_DESTROY_ID, 1349 END, 1350 ZERO, 1351 }; 1352 1353 static const enum index next_group_attr[] = { 1354 GROUP_INGRESS, 1355 GROUP_EGRESS, 1356 GROUP_TRANSFER, 1357 GROUP_SET_MISS_ACTIONS, 1358 ZERO, 1359 }; 1360 1361 static const enum index next_table_subcmd[] = { 1362 TABLE_CREATE, 1363 TABLE_DESTROY, 1364 ZERO, 1365 }; 1366 1367 static const enum index next_table_attr[] = { 1368 TABLE_CREATE_ID, 1369 TABLE_GROUP, 1370 TABLE_INSERTION_TYPE, 1371 TABLE_HASH_FUNC, 1372 TABLE_PRIORITY, 1373 TABLE_INGRESS, 1374 TABLE_EGRESS, 1375 TABLE_TRANSFER, 1376 TABLE_TRANSFER_WIRE_ORIG, 1377 TABLE_TRANSFER_VPORT_ORIG, 1378 TABLE_RULES_NUMBER, 1379 TABLE_PATTERN_TEMPLATE, 1380 TABLE_ACTIONS_TEMPLATE, 1381 END, 1382 ZERO, 1383 }; 1384 1385 static const enum index next_table_destroy_attr[] = { 1386 TABLE_DESTROY_ID, 1387 END, 1388 ZERO, 1389 }; 1390 1391 static const enum index next_queue_subcmd[] = { 1392 QUEUE_CREATE, 1393 QUEUE_DESTROY, 1394 QUEUE_UPDATE, 1395 QUEUE_AGED, 1396 QUEUE_INDIRECT_ACTION, 1397 ZERO, 1398 }; 1399 1400 static const enum index next_queue_destroy_attr[] = { 1401 QUEUE_DESTROY_ID, 1402 END, 1403 ZERO, 1404 }; 1405 1406 static const enum index next_qia_subcmd[] = { 1407 QUEUE_INDIRECT_ACTION_CREATE, 1408 QUEUE_INDIRECT_ACTION_UPDATE, 1409 QUEUE_INDIRECT_ACTION_DESTROY, 1410 QUEUE_INDIRECT_ACTION_QUERY, 1411 QUEUE_INDIRECT_ACTION_QUERY_UPDATE, 1412 ZERO, 1413 }; 1414 1415 static const enum index next_qia_create_attr[] = { 1416 QUEUE_INDIRECT_ACTION_CREATE_ID, 1417 QUEUE_INDIRECT_ACTION_INGRESS, 1418 QUEUE_INDIRECT_ACTION_EGRESS, 1419 QUEUE_INDIRECT_ACTION_TRANSFER, 1420 QUEUE_INDIRECT_ACTION_CREATE_POSTPONE, 1421 QUEUE_INDIRECT_ACTION_SPEC, 1422 QUEUE_INDIRECT_ACTION_LIST, 1423 ZERO, 1424 }; 1425 1426 static const enum index next_qia_update_attr[] = { 1427 QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE, 1428 QUEUE_INDIRECT_ACTION_SPEC, 1429 ZERO, 1430 }; 1431 1432 static const enum index next_qia_destroy_attr[] = { 1433 QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE, 1434 QUEUE_INDIRECT_ACTION_DESTROY_ID, 1435 END, 1436 ZERO, 1437 }; 1438 1439 static const enum index next_qia_query_attr[] = { 1440 QUEUE_INDIRECT_ACTION_QUERY_POSTPONE, 1441 END, 1442 ZERO, 1443 }; 1444 1445 static const enum index next_ia_create_attr[] = { 1446 INDIRECT_ACTION_CREATE_ID, 1447 INDIRECT_ACTION_INGRESS, 1448 INDIRECT_ACTION_EGRESS, 1449 INDIRECT_ACTION_TRANSFER, 1450 INDIRECT_ACTION_SPEC, 1451 INDIRECT_ACTION_LIST, 1452 INDIRECT_ACTION_FLOW_CONF, 1453 ZERO, 1454 }; 1455 1456 static const enum index next_ia[] = { 1457 INDIRECT_ACTION_ID2PTR, 1458 ACTION_NEXT, 1459 ZERO 1460 }; 1461 1462 static const enum index next_ial[] = { 1463 ACTION_INDIRECT_LIST_HANDLE, 1464 ACTION_INDIRECT_LIST_CONF, 1465 ACTION_NEXT, 1466 ZERO 1467 }; 1468 1469 static const enum index next_qia_qu_attr[] = { 1470 QUEUE_INDIRECT_ACTION_QU_MODE, 1471 QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE, 1472 INDIRECT_ACTION_SPEC, 1473 ZERO 1474 }; 1475 1476 static const enum index next_ia_qu_attr[] = { 1477 INDIRECT_ACTION_QU_MODE, 1478 INDIRECT_ACTION_SPEC, 1479 ZERO 1480 }; 1481 1482 static const enum index next_dump_subcmd[] = { 1483 DUMP_ALL, 1484 DUMP_ONE, 1485 DUMP_IS_USER_ID, 1486 ZERO, 1487 }; 1488 1489 static const enum index next_ia_subcmd[] = { 1490 INDIRECT_ACTION_CREATE, 1491 INDIRECT_ACTION_UPDATE, 1492 INDIRECT_ACTION_DESTROY, 1493 INDIRECT_ACTION_QUERY, 1494 INDIRECT_ACTION_QUERY_UPDATE, 1495 ZERO, 1496 }; 1497 1498 static const enum index next_vc_attr[] = { 1499 VC_GROUP, 1500 VC_PRIORITY, 1501 VC_INGRESS, 1502 VC_EGRESS, 1503 VC_TRANSFER, 1504 VC_TUNNEL_SET, 1505 VC_TUNNEL_MATCH, 1506 VC_USER_ID, 1507 ITEM_PATTERN, 1508 ZERO, 1509 }; 1510 1511 static const enum index next_destroy_attr[] = { 1512 DESTROY_RULE, 1513 DESTROY_IS_USER_ID, 1514 END, 1515 ZERO, 1516 }; 1517 1518 static const enum index next_dump_attr[] = { 1519 COMMON_FILE_PATH, 1520 END, 1521 ZERO, 1522 }; 1523 1524 static const enum index next_query_attr[] = { 1525 QUERY_IS_USER_ID, 1526 END, 1527 ZERO, 1528 }; 1529 1530 static const enum index next_list_attr[] = { 1531 LIST_GROUP, 1532 END, 1533 ZERO, 1534 }; 1535 1536 static const enum index next_aged_attr[] = { 1537 AGED_DESTROY, 1538 END, 1539 ZERO, 1540 }; 1541 1542 static const enum index next_ia_destroy_attr[] = { 1543 INDIRECT_ACTION_DESTROY_ID, 1544 END, 1545 ZERO, 1546 }; 1547 1548 static const enum index next_async_insert_subcmd[] = { 1549 QUEUE_PATTERN_TEMPLATE, 1550 QUEUE_RULE_ID, 1551 ZERO, 1552 }; 1553 1554 static const enum index item_param[] = { 1555 ITEM_PARAM_IS, 1556 ITEM_PARAM_SPEC, 1557 ITEM_PARAM_LAST, 1558 ITEM_PARAM_MASK, 1559 ITEM_PARAM_PREFIX, 1560 ZERO, 1561 }; 1562 1563 static const enum index next_item[] = { 1564 ITEM_END, 1565 ITEM_VOID, 1566 ITEM_INVERT, 1567 ITEM_ANY, 1568 ITEM_PORT_ID, 1569 ITEM_MARK, 1570 ITEM_RAW, 1571 ITEM_ETH, 1572 ITEM_VLAN, 1573 ITEM_IPV4, 1574 ITEM_IPV6, 1575 ITEM_ICMP, 1576 ITEM_UDP, 1577 ITEM_TCP, 1578 ITEM_SCTP, 1579 ITEM_VXLAN, 1580 ITEM_E_TAG, 1581 ITEM_NVGRE, 1582 ITEM_MPLS, 1583 ITEM_GRE, 1584 ITEM_FUZZY, 1585 ITEM_GTP, 1586 ITEM_GTPC, 1587 ITEM_GTPU, 1588 ITEM_GENEVE, 1589 ITEM_VXLAN_GPE, 1590 ITEM_ARP_ETH_IPV4, 1591 ITEM_IPV6_EXT, 1592 ITEM_IPV6_FRAG_EXT, 1593 ITEM_IPV6_ROUTING_EXT, 1594 ITEM_ICMP6, 1595 ITEM_ICMP6_ECHO_REQUEST, 1596 ITEM_ICMP6_ECHO_REPLY, 1597 ITEM_ICMP6_ND_NS, 1598 ITEM_ICMP6_ND_NA, 1599 ITEM_ICMP6_ND_OPT, 1600 ITEM_ICMP6_ND_OPT_SLA_ETH, 1601 ITEM_ICMP6_ND_OPT_TLA_ETH, 1602 ITEM_META, 1603 ITEM_RANDOM, 1604 ITEM_GRE_KEY, 1605 ITEM_GRE_OPTION, 1606 ITEM_GTP_PSC, 1607 ITEM_PPPOES, 1608 ITEM_PPPOED, 1609 ITEM_PPPOE_PROTO_ID, 1610 ITEM_HIGIG2, 1611 ITEM_TAG, 1612 ITEM_L2TPV3OIP, 1613 ITEM_ESP, 1614 ITEM_AH, 1615 ITEM_PFCP, 1616 ITEM_ECPRI, 1617 ITEM_GENEVE_OPT, 1618 ITEM_INTEGRITY, 1619 ITEM_CONNTRACK, 1620 ITEM_PORT_REPRESENTOR, 1621 ITEM_REPRESENTED_PORT, 1622 ITEM_FLEX, 1623 ITEM_L2TPV2, 1624 ITEM_PPP, 1625 ITEM_METER, 1626 ITEM_QUOTA, 1627 ITEM_AGGR_AFFINITY, 1628 ITEM_TX_QUEUE, 1629 ITEM_IB_BTH, 1630 ITEM_PTYPE, 1631 ITEM_NSH, 1632 ITEM_COMPARE, 1633 END_SET, 1634 ZERO, 1635 }; 1636 1637 static const enum index item_fuzzy[] = { 1638 ITEM_FUZZY_THRESH, 1639 ITEM_NEXT, 1640 ZERO, 1641 }; 1642 1643 static const enum index item_any[] = { 1644 ITEM_ANY_NUM, 1645 ITEM_NEXT, 1646 ZERO, 1647 }; 1648 1649 static const enum index item_port_id[] = { 1650 ITEM_PORT_ID_ID, 1651 ITEM_NEXT, 1652 ZERO, 1653 }; 1654 1655 static const enum index item_mark[] = { 1656 ITEM_MARK_ID, 1657 ITEM_NEXT, 1658 ZERO, 1659 }; 1660 1661 static const enum index item_raw[] = { 1662 ITEM_RAW_RELATIVE, 1663 ITEM_RAW_SEARCH, 1664 ITEM_RAW_OFFSET, 1665 ITEM_RAW_LIMIT, 1666 ITEM_RAW_PATTERN, 1667 ITEM_RAW_PATTERN_HEX, 1668 ITEM_NEXT, 1669 ZERO, 1670 }; 1671 1672 static const enum index item_eth[] = { 1673 ITEM_ETH_DST, 1674 ITEM_ETH_SRC, 1675 ITEM_ETH_TYPE, 1676 ITEM_ETH_HAS_VLAN, 1677 ITEM_NEXT, 1678 ZERO, 1679 }; 1680 1681 static const enum index item_vlan[] = { 1682 ITEM_VLAN_TCI, 1683 ITEM_VLAN_PCP, 1684 ITEM_VLAN_DEI, 1685 ITEM_VLAN_VID, 1686 ITEM_VLAN_INNER_TYPE, 1687 ITEM_VLAN_HAS_MORE_VLAN, 1688 ITEM_NEXT, 1689 ZERO, 1690 }; 1691 1692 static const enum index item_ipv4[] = { 1693 ITEM_IPV4_VER_IHL, 1694 ITEM_IPV4_TOS, 1695 ITEM_IPV4_LENGTH, 1696 ITEM_IPV4_ID, 1697 ITEM_IPV4_FRAGMENT_OFFSET, 1698 ITEM_IPV4_TTL, 1699 ITEM_IPV4_PROTO, 1700 ITEM_IPV4_SRC, 1701 ITEM_IPV4_DST, 1702 ITEM_NEXT, 1703 ZERO, 1704 }; 1705 1706 static const enum index item_ipv6[] = { 1707 ITEM_IPV6_TC, 1708 ITEM_IPV6_FLOW, 1709 ITEM_IPV6_LEN, 1710 ITEM_IPV6_PROTO, 1711 ITEM_IPV6_HOP, 1712 ITEM_IPV6_SRC, 1713 ITEM_IPV6_DST, 1714 ITEM_IPV6_HAS_FRAG_EXT, 1715 ITEM_IPV6_ROUTING_EXT, 1716 ITEM_NEXT, 1717 ZERO, 1718 }; 1719 1720 static const enum index item_ipv6_routing_ext[] = { 1721 ITEM_IPV6_ROUTING_EXT_TYPE, 1722 ITEM_IPV6_ROUTING_EXT_NEXT_HDR, 1723 ITEM_IPV6_ROUTING_EXT_SEG_LEFT, 1724 ITEM_NEXT, 1725 ZERO, 1726 }; 1727 1728 static const enum index item_icmp[] = { 1729 ITEM_ICMP_TYPE, 1730 ITEM_ICMP_CODE, 1731 ITEM_ICMP_IDENT, 1732 ITEM_ICMP_SEQ, 1733 ITEM_NEXT, 1734 ZERO, 1735 }; 1736 1737 static const enum index item_udp[] = { 1738 ITEM_UDP_SRC, 1739 ITEM_UDP_DST, 1740 ITEM_NEXT, 1741 ZERO, 1742 }; 1743 1744 static const enum index item_tcp[] = { 1745 ITEM_TCP_SRC, 1746 ITEM_TCP_DST, 1747 ITEM_TCP_FLAGS, 1748 ITEM_NEXT, 1749 ZERO, 1750 }; 1751 1752 static const enum index item_sctp[] = { 1753 ITEM_SCTP_SRC, 1754 ITEM_SCTP_DST, 1755 ITEM_SCTP_TAG, 1756 ITEM_SCTP_CKSUM, 1757 ITEM_NEXT, 1758 ZERO, 1759 }; 1760 1761 static const enum index item_vxlan[] = { 1762 ITEM_VXLAN_VNI, 1763 ITEM_VXLAN_LAST_RSVD, 1764 ITEM_NEXT, 1765 ZERO, 1766 }; 1767 1768 static const enum index item_e_tag[] = { 1769 ITEM_E_TAG_GRP_ECID_B, 1770 ITEM_NEXT, 1771 ZERO, 1772 }; 1773 1774 static const enum index item_nvgre[] = { 1775 ITEM_NVGRE_TNI, 1776 ITEM_NEXT, 1777 ZERO, 1778 }; 1779 1780 static const enum index item_mpls[] = { 1781 ITEM_MPLS_LABEL, 1782 ITEM_MPLS_TC, 1783 ITEM_MPLS_S, 1784 ITEM_MPLS_TTL, 1785 ITEM_NEXT, 1786 ZERO, 1787 }; 1788 1789 static const enum index item_gre[] = { 1790 ITEM_GRE_PROTO, 1791 ITEM_GRE_C_RSVD0_VER, 1792 ITEM_GRE_C_BIT, 1793 ITEM_GRE_K_BIT, 1794 ITEM_GRE_S_BIT, 1795 ITEM_NEXT, 1796 ZERO, 1797 }; 1798 1799 static const enum index item_gre_key[] = { 1800 ITEM_GRE_KEY_VALUE, 1801 ITEM_NEXT, 1802 ZERO, 1803 }; 1804 1805 static const enum index item_gre_option[] = { 1806 ITEM_GRE_OPTION_CHECKSUM, 1807 ITEM_GRE_OPTION_KEY, 1808 ITEM_GRE_OPTION_SEQUENCE, 1809 ITEM_NEXT, 1810 ZERO, 1811 }; 1812 1813 static const enum index item_gtp[] = { 1814 ITEM_GTP_FLAGS, 1815 ITEM_GTP_MSG_TYPE, 1816 ITEM_GTP_TEID, 1817 ITEM_NEXT, 1818 ZERO, 1819 }; 1820 1821 static const enum index item_geneve[] = { 1822 ITEM_GENEVE_VNI, 1823 ITEM_GENEVE_PROTO, 1824 ITEM_GENEVE_OPTLEN, 1825 ITEM_NEXT, 1826 ZERO, 1827 }; 1828 1829 static const enum index item_vxlan_gpe[] = { 1830 ITEM_VXLAN_GPE_VNI, 1831 ITEM_VXLAN_GPE_PROTO, 1832 ITEM_NEXT, 1833 ZERO, 1834 }; 1835 1836 static const enum index item_arp_eth_ipv4[] = { 1837 ITEM_ARP_ETH_IPV4_SHA, 1838 ITEM_ARP_ETH_IPV4_SPA, 1839 ITEM_ARP_ETH_IPV4_THA, 1840 ITEM_ARP_ETH_IPV4_TPA, 1841 ITEM_NEXT, 1842 ZERO, 1843 }; 1844 1845 static const enum index item_ipv6_ext[] = { 1846 ITEM_IPV6_EXT_NEXT_HDR, 1847 ITEM_NEXT, 1848 ZERO, 1849 }; 1850 1851 static const enum index item_ipv6_frag_ext[] = { 1852 ITEM_IPV6_FRAG_EXT_NEXT_HDR, 1853 ITEM_IPV6_FRAG_EXT_FRAG_DATA, 1854 ITEM_IPV6_FRAG_EXT_ID, 1855 ITEM_NEXT, 1856 ZERO, 1857 }; 1858 1859 static const enum index item_icmp6[] = { 1860 ITEM_ICMP6_TYPE, 1861 ITEM_ICMP6_CODE, 1862 ITEM_NEXT, 1863 ZERO, 1864 }; 1865 1866 static const enum index item_icmp6_echo_request[] = { 1867 ITEM_ICMP6_ECHO_REQUEST_ID, 1868 ITEM_ICMP6_ECHO_REQUEST_SEQ, 1869 ITEM_NEXT, 1870 ZERO, 1871 }; 1872 1873 static const enum index item_icmp6_echo_reply[] = { 1874 ITEM_ICMP6_ECHO_REPLY_ID, 1875 ITEM_ICMP6_ECHO_REPLY_SEQ, 1876 ITEM_NEXT, 1877 ZERO, 1878 }; 1879 1880 static const enum index item_icmp6_nd_ns[] = { 1881 ITEM_ICMP6_ND_NS_TARGET_ADDR, 1882 ITEM_NEXT, 1883 ZERO, 1884 }; 1885 1886 static const enum index item_icmp6_nd_na[] = { 1887 ITEM_ICMP6_ND_NA_TARGET_ADDR, 1888 ITEM_NEXT, 1889 ZERO, 1890 }; 1891 1892 static const enum index item_icmp6_nd_opt[] = { 1893 ITEM_ICMP6_ND_OPT_TYPE, 1894 ITEM_NEXT, 1895 ZERO, 1896 }; 1897 1898 static const enum index item_icmp6_nd_opt_sla_eth[] = { 1899 ITEM_ICMP6_ND_OPT_SLA_ETH_SLA, 1900 ITEM_NEXT, 1901 ZERO, 1902 }; 1903 1904 static const enum index item_icmp6_nd_opt_tla_eth[] = { 1905 ITEM_ICMP6_ND_OPT_TLA_ETH_TLA, 1906 ITEM_NEXT, 1907 ZERO, 1908 }; 1909 1910 static const enum index item_meta[] = { 1911 ITEM_META_DATA, 1912 ITEM_NEXT, 1913 ZERO, 1914 }; 1915 1916 static const enum index item_random[] = { 1917 ITEM_RANDOM_VALUE, 1918 ITEM_NEXT, 1919 ZERO, 1920 }; 1921 1922 static const enum index item_gtp_psc[] = { 1923 ITEM_GTP_PSC_QFI, 1924 ITEM_GTP_PSC_PDU_T, 1925 ITEM_NEXT, 1926 ZERO, 1927 }; 1928 1929 static const enum index item_pppoed[] = { 1930 ITEM_PPPOE_SEID, 1931 ITEM_NEXT, 1932 ZERO, 1933 }; 1934 1935 static const enum index item_pppoes[] = { 1936 ITEM_PPPOE_SEID, 1937 ITEM_NEXT, 1938 ZERO, 1939 }; 1940 1941 static const enum index item_pppoe_proto_id[] = { 1942 ITEM_NEXT, 1943 ZERO, 1944 }; 1945 1946 static const enum index item_higig2[] = { 1947 ITEM_HIGIG2_CLASSIFICATION, 1948 ITEM_HIGIG2_VID, 1949 ITEM_NEXT, 1950 ZERO, 1951 }; 1952 1953 static const enum index item_esp[] = { 1954 ITEM_ESP_SPI, 1955 ITEM_NEXT, 1956 ZERO, 1957 }; 1958 1959 static const enum index item_ah[] = { 1960 ITEM_AH_SPI, 1961 ITEM_NEXT, 1962 ZERO, 1963 }; 1964 1965 static const enum index item_pfcp[] = { 1966 ITEM_PFCP_S_FIELD, 1967 ITEM_PFCP_SEID, 1968 ITEM_NEXT, 1969 ZERO, 1970 }; 1971 1972 static const enum index next_set_raw[] = { 1973 SET_RAW_INDEX, 1974 ITEM_ETH, 1975 ZERO, 1976 }; 1977 1978 static const enum index item_tag[] = { 1979 ITEM_TAG_DATA, 1980 ITEM_TAG_INDEX, 1981 ITEM_NEXT, 1982 ZERO, 1983 }; 1984 1985 static const enum index item_l2tpv3oip[] = { 1986 ITEM_L2TPV3OIP_SESSION_ID, 1987 ITEM_NEXT, 1988 ZERO, 1989 }; 1990 1991 static const enum index item_ecpri[] = { 1992 ITEM_ECPRI_COMMON, 1993 ITEM_NEXT, 1994 ZERO, 1995 }; 1996 1997 static const enum index item_ecpri_common[] = { 1998 ITEM_ECPRI_COMMON_TYPE, 1999 ZERO, 2000 }; 2001 2002 static const enum index item_ecpri_common_type[] = { 2003 ITEM_ECPRI_COMMON_TYPE_IQ_DATA, 2004 ITEM_ECPRI_COMMON_TYPE_RTC_CTRL, 2005 ITEM_ECPRI_COMMON_TYPE_DLY_MSR, 2006 ZERO, 2007 }; 2008 2009 static const enum index item_geneve_opt[] = { 2010 ITEM_GENEVE_OPT_CLASS, 2011 ITEM_GENEVE_OPT_TYPE, 2012 ITEM_GENEVE_OPT_LENGTH, 2013 ITEM_GENEVE_OPT_DATA, 2014 ITEM_NEXT, 2015 ZERO, 2016 }; 2017 2018 static const enum index item_integrity[] = { 2019 ITEM_INTEGRITY_LEVEL, 2020 ITEM_INTEGRITY_VALUE, 2021 ZERO, 2022 }; 2023 2024 static const enum index item_integrity_lv[] = { 2025 ITEM_INTEGRITY_LEVEL, 2026 ITEM_INTEGRITY_VALUE, 2027 ITEM_NEXT, 2028 ZERO, 2029 }; 2030 2031 static const enum index item_port_representor[] = { 2032 ITEM_PORT_REPRESENTOR_PORT_ID, 2033 ITEM_NEXT, 2034 ZERO, 2035 }; 2036 2037 static const enum index item_represented_port[] = { 2038 ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID, 2039 ITEM_NEXT, 2040 ZERO, 2041 }; 2042 2043 static const enum index item_flex[] = { 2044 ITEM_FLEX_PATTERN_HANDLE, 2045 ITEM_FLEX_ITEM_HANDLE, 2046 ITEM_NEXT, 2047 ZERO, 2048 }; 2049 2050 static const enum index item_l2tpv2[] = { 2051 ITEM_L2TPV2_TYPE, 2052 ITEM_NEXT, 2053 ZERO, 2054 }; 2055 2056 static const enum index item_l2tpv2_type[] = { 2057 ITEM_L2TPV2_TYPE_DATA, 2058 ITEM_L2TPV2_TYPE_DATA_L, 2059 ITEM_L2TPV2_TYPE_DATA_S, 2060 ITEM_L2TPV2_TYPE_DATA_O, 2061 ITEM_L2TPV2_TYPE_DATA_L_S, 2062 ITEM_L2TPV2_TYPE_CTRL, 2063 ZERO, 2064 }; 2065 2066 static const enum index item_l2tpv2_type_data[] = { 2067 ITEM_L2TPV2_MSG_DATA_TUNNEL_ID, 2068 ITEM_L2TPV2_MSG_DATA_SESSION_ID, 2069 ITEM_NEXT, 2070 ZERO, 2071 }; 2072 2073 static const enum index item_l2tpv2_type_data_l[] = { 2074 ITEM_L2TPV2_MSG_DATA_L_LENGTH, 2075 ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID, 2076 ITEM_L2TPV2_MSG_DATA_L_SESSION_ID, 2077 ITEM_NEXT, 2078 ZERO, 2079 }; 2080 2081 static const enum index item_l2tpv2_type_data_s[] = { 2082 ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID, 2083 ITEM_L2TPV2_MSG_DATA_S_SESSION_ID, 2084 ITEM_L2TPV2_MSG_DATA_S_NS, 2085 ITEM_L2TPV2_MSG_DATA_S_NR, 2086 ITEM_NEXT, 2087 ZERO, 2088 }; 2089 2090 static const enum index item_l2tpv2_type_data_o[] = { 2091 ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID, 2092 ITEM_L2TPV2_MSG_DATA_O_SESSION_ID, 2093 ITEM_L2TPV2_MSG_DATA_O_OFFSET, 2094 ITEM_NEXT, 2095 ZERO, 2096 }; 2097 2098 static const enum index item_l2tpv2_type_data_l_s[] = { 2099 ITEM_L2TPV2_MSG_DATA_L_S_LENGTH, 2100 ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID, 2101 ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID, 2102 ITEM_L2TPV2_MSG_DATA_L_S_NS, 2103 ITEM_L2TPV2_MSG_DATA_L_S_NR, 2104 ITEM_NEXT, 2105 ZERO, 2106 }; 2107 2108 static const enum index item_l2tpv2_type_ctrl[] = { 2109 ITEM_L2TPV2_MSG_CTRL_LENGTH, 2110 ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID, 2111 ITEM_L2TPV2_MSG_CTRL_SESSION_ID, 2112 ITEM_L2TPV2_MSG_CTRL_NS, 2113 ITEM_L2TPV2_MSG_CTRL_NR, 2114 ITEM_NEXT, 2115 ZERO, 2116 }; 2117 2118 static const enum index item_ppp[] = { 2119 ITEM_PPP_ADDR, 2120 ITEM_PPP_CTRL, 2121 ITEM_PPP_PROTO_ID, 2122 ITEM_NEXT, 2123 ZERO, 2124 }; 2125 2126 static const enum index item_meter[] = { 2127 ITEM_METER_COLOR, 2128 ITEM_NEXT, 2129 ZERO, 2130 }; 2131 2132 static const enum index item_quota[] = { 2133 ITEM_QUOTA_STATE, 2134 ITEM_NEXT, 2135 ZERO, 2136 }; 2137 2138 static const enum index item_aggr_affinity[] = { 2139 ITEM_AGGR_AFFINITY_VALUE, 2140 ITEM_NEXT, 2141 ZERO, 2142 }; 2143 2144 static const enum index item_tx_queue[] = { 2145 ITEM_TX_QUEUE_VALUE, 2146 ITEM_NEXT, 2147 ZERO, 2148 }; 2149 2150 static const enum index item_ib_bth[] = { 2151 ITEM_IB_BTH_OPCODE, 2152 ITEM_IB_BTH_PKEY, 2153 ITEM_IB_BTH_DST_QPN, 2154 ITEM_IB_BTH_PSN, 2155 ITEM_NEXT, 2156 ZERO, 2157 }; 2158 2159 static const enum index item_ptype[] = { 2160 ITEM_PTYPE_VALUE, 2161 ITEM_NEXT, 2162 ZERO, 2163 }; 2164 2165 static const enum index item_nsh[] = { 2166 ITEM_NEXT, 2167 ZERO, 2168 }; 2169 2170 static const enum index item_compare_field[] = { 2171 ITEM_COMPARE_OP, 2172 ITEM_COMPARE_FIELD_A_TYPE, 2173 ITEM_COMPARE_FIELD_B_TYPE, 2174 ITEM_NEXT, 2175 ZERO, 2176 }; 2177 2178 static const enum index compare_field_a[] = { 2179 ITEM_COMPARE_FIELD_A_TYPE, 2180 ITEM_COMPARE_FIELD_A_LEVEL, 2181 ITEM_COMPARE_FIELD_A_TAG_INDEX, 2182 ITEM_COMPARE_FIELD_A_TYPE_ID, 2183 ITEM_COMPARE_FIELD_A_CLASS_ID, 2184 ITEM_COMPARE_FIELD_A_OFFSET, 2185 ITEM_COMPARE_FIELD_B_TYPE, 2186 ZERO, 2187 }; 2188 2189 static const enum index compare_field_b[] = { 2190 ITEM_COMPARE_FIELD_B_TYPE, 2191 ITEM_COMPARE_FIELD_B_LEVEL, 2192 ITEM_COMPARE_FIELD_B_TAG_INDEX, 2193 ITEM_COMPARE_FIELD_B_TYPE_ID, 2194 ITEM_COMPARE_FIELD_B_CLASS_ID, 2195 ITEM_COMPARE_FIELD_B_OFFSET, 2196 ITEM_COMPARE_FIELD_B_VALUE, 2197 ITEM_COMPARE_FIELD_B_POINTER, 2198 ITEM_COMPARE_FIELD_WIDTH, 2199 ZERO, 2200 }; 2201 2202 static const enum index next_action[] = { 2203 ACTION_END, 2204 ACTION_VOID, 2205 ACTION_PASSTHRU, 2206 ACTION_SKIP_CMAN, 2207 ACTION_JUMP, 2208 ACTION_MARK, 2209 ACTION_FLAG, 2210 ACTION_QUEUE, 2211 ACTION_DROP, 2212 ACTION_COUNT, 2213 ACTION_RSS, 2214 ACTION_PF, 2215 ACTION_VF, 2216 ACTION_PORT_ID, 2217 ACTION_METER, 2218 ACTION_METER_COLOR, 2219 ACTION_METER_MARK, 2220 ACTION_OF_DEC_NW_TTL, 2221 ACTION_OF_POP_VLAN, 2222 ACTION_OF_PUSH_VLAN, 2223 ACTION_OF_SET_VLAN_VID, 2224 ACTION_OF_SET_VLAN_PCP, 2225 ACTION_OF_POP_MPLS, 2226 ACTION_OF_PUSH_MPLS, 2227 ACTION_VXLAN_ENCAP, 2228 ACTION_VXLAN_DECAP, 2229 ACTION_NVGRE_ENCAP, 2230 ACTION_NVGRE_DECAP, 2231 ACTION_L2_ENCAP, 2232 ACTION_L2_DECAP, 2233 ACTION_MPLSOGRE_ENCAP, 2234 ACTION_MPLSOGRE_DECAP, 2235 ACTION_MPLSOUDP_ENCAP, 2236 ACTION_MPLSOUDP_DECAP, 2237 ACTION_SET_IPV4_SRC, 2238 ACTION_SET_IPV4_DST, 2239 ACTION_SET_IPV6_SRC, 2240 ACTION_SET_IPV6_DST, 2241 ACTION_SET_TP_SRC, 2242 ACTION_SET_TP_DST, 2243 ACTION_MAC_SWAP, 2244 ACTION_DEC_TTL, 2245 ACTION_SET_TTL, 2246 ACTION_SET_MAC_SRC, 2247 ACTION_SET_MAC_DST, 2248 ACTION_INC_TCP_SEQ, 2249 ACTION_DEC_TCP_SEQ, 2250 ACTION_INC_TCP_ACK, 2251 ACTION_DEC_TCP_ACK, 2252 ACTION_RAW_ENCAP, 2253 ACTION_RAW_DECAP, 2254 ACTION_SET_TAG, 2255 ACTION_SET_META, 2256 ACTION_SET_IPV4_DSCP, 2257 ACTION_SET_IPV6_DSCP, 2258 ACTION_AGE, 2259 ACTION_AGE_UPDATE, 2260 ACTION_SAMPLE, 2261 ACTION_INDIRECT, 2262 ACTION_INDIRECT_LIST, 2263 ACTION_SHARED_INDIRECT, 2264 ACTION_MODIFY_FIELD, 2265 ACTION_CONNTRACK, 2266 ACTION_CONNTRACK_UPDATE, 2267 ACTION_PORT_REPRESENTOR, 2268 ACTION_REPRESENTED_PORT, 2269 ACTION_SEND_TO_KERNEL, 2270 ACTION_QUOTA_CREATE, 2271 ACTION_QUOTA_QU, 2272 ACTION_IPV6_EXT_REMOVE, 2273 ACTION_IPV6_EXT_PUSH, 2274 ACTION_NAT64, 2275 ZERO, 2276 }; 2277 2278 static const enum index action_quota_create[] = { 2279 ACTION_QUOTA_CREATE_LIMIT, 2280 ACTION_QUOTA_CREATE_MODE, 2281 ACTION_NEXT, 2282 ZERO 2283 }; 2284 2285 static const enum index action_quota_update[] = { 2286 ACTION_QUOTA_QU_LIMIT, 2287 ACTION_QUOTA_QU_UPDATE_OP, 2288 ACTION_NEXT, 2289 ZERO 2290 }; 2291 2292 static const enum index action_mark[] = { 2293 ACTION_MARK_ID, 2294 ACTION_NEXT, 2295 ZERO, 2296 }; 2297 2298 static const enum index action_queue[] = { 2299 ACTION_QUEUE_INDEX, 2300 ACTION_NEXT, 2301 ZERO, 2302 }; 2303 2304 static const enum index action_count[] = { 2305 ACTION_COUNT_ID, 2306 ACTION_NEXT, 2307 ZERO, 2308 }; 2309 2310 static const enum index action_rss[] = { 2311 ACTION_RSS_FUNC, 2312 ACTION_RSS_LEVEL, 2313 ACTION_RSS_TYPES, 2314 ACTION_RSS_KEY, 2315 ACTION_RSS_KEY_LEN, 2316 ACTION_RSS_QUEUES, 2317 ACTION_NEXT, 2318 ZERO, 2319 }; 2320 2321 static const enum index action_vf[] = { 2322 ACTION_VF_ORIGINAL, 2323 ACTION_VF_ID, 2324 ACTION_NEXT, 2325 ZERO, 2326 }; 2327 2328 static const enum index action_port_id[] = { 2329 ACTION_PORT_ID_ORIGINAL, 2330 ACTION_PORT_ID_ID, 2331 ACTION_NEXT, 2332 ZERO, 2333 }; 2334 2335 static const enum index action_meter[] = { 2336 ACTION_METER_ID, 2337 ACTION_NEXT, 2338 ZERO, 2339 }; 2340 2341 static const enum index action_meter_color[] = { 2342 ACTION_METER_COLOR_TYPE, 2343 ACTION_NEXT, 2344 ZERO, 2345 }; 2346 2347 static const enum index action_meter_mark[] = { 2348 ACTION_METER_PROFILE, 2349 ACTION_METER_POLICY, 2350 ACTION_METER_COLOR_MODE, 2351 ACTION_METER_STATE, 2352 ACTION_NEXT, 2353 ZERO, 2354 }; 2355 2356 static const enum index action_of_push_vlan[] = { 2357 ACTION_OF_PUSH_VLAN_ETHERTYPE, 2358 ACTION_NEXT, 2359 ZERO, 2360 }; 2361 2362 static const enum index action_of_set_vlan_vid[] = { 2363 ACTION_OF_SET_VLAN_VID_VLAN_VID, 2364 ACTION_NEXT, 2365 ZERO, 2366 }; 2367 2368 static const enum index action_of_set_vlan_pcp[] = { 2369 ACTION_OF_SET_VLAN_PCP_VLAN_PCP, 2370 ACTION_NEXT, 2371 ZERO, 2372 }; 2373 2374 static const enum index action_of_pop_mpls[] = { 2375 ACTION_OF_POP_MPLS_ETHERTYPE, 2376 ACTION_NEXT, 2377 ZERO, 2378 }; 2379 2380 static const enum index action_of_push_mpls[] = { 2381 ACTION_OF_PUSH_MPLS_ETHERTYPE, 2382 ACTION_NEXT, 2383 ZERO, 2384 }; 2385 2386 static const enum index action_set_ipv4_src[] = { 2387 ACTION_SET_IPV4_SRC_IPV4_SRC, 2388 ACTION_NEXT, 2389 ZERO, 2390 }; 2391 2392 static const enum index action_set_mac_src[] = { 2393 ACTION_SET_MAC_SRC_MAC_SRC, 2394 ACTION_NEXT, 2395 ZERO, 2396 }; 2397 2398 static const enum index action_set_ipv4_dst[] = { 2399 ACTION_SET_IPV4_DST_IPV4_DST, 2400 ACTION_NEXT, 2401 ZERO, 2402 }; 2403 2404 static const enum index action_set_ipv6_src[] = { 2405 ACTION_SET_IPV6_SRC_IPV6_SRC, 2406 ACTION_NEXT, 2407 ZERO, 2408 }; 2409 2410 static const enum index action_set_ipv6_dst[] = { 2411 ACTION_SET_IPV6_DST_IPV6_DST, 2412 ACTION_NEXT, 2413 ZERO, 2414 }; 2415 2416 static const enum index action_set_tp_src[] = { 2417 ACTION_SET_TP_SRC_TP_SRC, 2418 ACTION_NEXT, 2419 ZERO, 2420 }; 2421 2422 static const enum index action_set_tp_dst[] = { 2423 ACTION_SET_TP_DST_TP_DST, 2424 ACTION_NEXT, 2425 ZERO, 2426 }; 2427 2428 static const enum index action_set_ttl[] = { 2429 ACTION_SET_TTL_TTL, 2430 ACTION_NEXT, 2431 ZERO, 2432 }; 2433 2434 static const enum index action_jump[] = { 2435 ACTION_JUMP_GROUP, 2436 ACTION_NEXT, 2437 ZERO, 2438 }; 2439 2440 static const enum index action_set_mac_dst[] = { 2441 ACTION_SET_MAC_DST_MAC_DST, 2442 ACTION_NEXT, 2443 ZERO, 2444 }; 2445 2446 static const enum index action_inc_tcp_seq[] = { 2447 ACTION_INC_TCP_SEQ_VALUE, 2448 ACTION_NEXT, 2449 ZERO, 2450 }; 2451 2452 static const enum index action_dec_tcp_seq[] = { 2453 ACTION_DEC_TCP_SEQ_VALUE, 2454 ACTION_NEXT, 2455 ZERO, 2456 }; 2457 2458 static const enum index action_inc_tcp_ack[] = { 2459 ACTION_INC_TCP_ACK_VALUE, 2460 ACTION_NEXT, 2461 ZERO, 2462 }; 2463 2464 static const enum index action_dec_tcp_ack[] = { 2465 ACTION_DEC_TCP_ACK_VALUE, 2466 ACTION_NEXT, 2467 ZERO, 2468 }; 2469 2470 static const enum index action_raw_encap[] = { 2471 ACTION_RAW_ENCAP_SIZE, 2472 ACTION_RAW_ENCAP_INDEX, 2473 ACTION_NEXT, 2474 ZERO, 2475 }; 2476 2477 static const enum index action_raw_decap[] = { 2478 ACTION_RAW_DECAP_INDEX, 2479 ACTION_NEXT, 2480 ZERO, 2481 }; 2482 2483 static const enum index action_ipv6_ext_remove[] = { 2484 ACTION_IPV6_EXT_REMOVE_INDEX, 2485 ACTION_NEXT, 2486 ZERO, 2487 }; 2488 2489 static const enum index action_ipv6_ext_push[] = { 2490 ACTION_IPV6_EXT_PUSH_INDEX, 2491 ACTION_NEXT, 2492 ZERO, 2493 }; 2494 2495 static const enum index action_set_tag[] = { 2496 ACTION_SET_TAG_DATA, 2497 ACTION_SET_TAG_INDEX, 2498 ACTION_SET_TAG_MASK, 2499 ACTION_NEXT, 2500 ZERO, 2501 }; 2502 2503 static const enum index action_set_meta[] = { 2504 ACTION_SET_META_DATA, 2505 ACTION_SET_META_MASK, 2506 ACTION_NEXT, 2507 ZERO, 2508 }; 2509 2510 static const enum index action_set_ipv4_dscp[] = { 2511 ACTION_SET_IPV4_DSCP_VALUE, 2512 ACTION_NEXT, 2513 ZERO, 2514 }; 2515 2516 static const enum index action_set_ipv6_dscp[] = { 2517 ACTION_SET_IPV6_DSCP_VALUE, 2518 ACTION_NEXT, 2519 ZERO, 2520 }; 2521 2522 static const enum index action_age[] = { 2523 ACTION_AGE, 2524 ACTION_AGE_TIMEOUT, 2525 ACTION_NEXT, 2526 ZERO, 2527 }; 2528 2529 static const enum index action_age_update[] = { 2530 ACTION_AGE_UPDATE, 2531 ACTION_AGE_UPDATE_TIMEOUT, 2532 ACTION_AGE_UPDATE_TOUCH, 2533 ACTION_NEXT, 2534 ZERO, 2535 }; 2536 2537 static const enum index action_sample[] = { 2538 ACTION_SAMPLE, 2539 ACTION_SAMPLE_RATIO, 2540 ACTION_SAMPLE_INDEX, 2541 ACTION_NEXT, 2542 ZERO, 2543 }; 2544 2545 static const enum index next_action_sample[] = { 2546 ACTION_QUEUE, 2547 ACTION_RSS, 2548 ACTION_MARK, 2549 ACTION_COUNT, 2550 ACTION_PORT_ID, 2551 ACTION_RAW_ENCAP, 2552 ACTION_VXLAN_ENCAP, 2553 ACTION_NVGRE_ENCAP, 2554 ACTION_REPRESENTED_PORT, 2555 ACTION_PORT_REPRESENTOR, 2556 ACTION_NEXT, 2557 ZERO, 2558 }; 2559 2560 static const enum index item_ipv6_push_ext[] = { 2561 ITEM_IPV6_PUSH_REMOVE_EXT, 2562 ZERO, 2563 }; 2564 2565 static const enum index item_ipv6_push_ext_type[] = { 2566 ITEM_IPV6_PUSH_REMOVE_EXT_TYPE, 2567 ZERO, 2568 }; 2569 2570 static const enum index item_ipv6_push_ext_header[] = { 2571 ITEM_IPV6_ROUTING_EXT, 2572 ITEM_NEXT, 2573 ZERO, 2574 }; 2575 2576 static const enum index action_modify_field_dst[] = { 2577 ACTION_MODIFY_FIELD_DST_LEVEL, 2578 ACTION_MODIFY_FIELD_DST_TAG_INDEX, 2579 ACTION_MODIFY_FIELD_DST_TYPE_ID, 2580 ACTION_MODIFY_FIELD_DST_CLASS_ID, 2581 ACTION_MODIFY_FIELD_DST_OFFSET, 2582 ACTION_MODIFY_FIELD_SRC_TYPE, 2583 ZERO, 2584 }; 2585 2586 static const enum index action_modify_field_src[] = { 2587 ACTION_MODIFY_FIELD_SRC_LEVEL, 2588 ACTION_MODIFY_FIELD_SRC_TAG_INDEX, 2589 ACTION_MODIFY_FIELD_SRC_TYPE_ID, 2590 ACTION_MODIFY_FIELD_SRC_CLASS_ID, 2591 ACTION_MODIFY_FIELD_SRC_OFFSET, 2592 ACTION_MODIFY_FIELD_SRC_VALUE, 2593 ACTION_MODIFY_FIELD_SRC_POINTER, 2594 ACTION_MODIFY_FIELD_WIDTH, 2595 ZERO, 2596 }; 2597 2598 static const enum index action_update_conntrack[] = { 2599 ACTION_CONNTRACK_UPDATE_DIR, 2600 ACTION_CONNTRACK_UPDATE_CTX, 2601 ACTION_NEXT, 2602 ZERO, 2603 }; 2604 2605 static const enum index action_port_representor[] = { 2606 ACTION_PORT_REPRESENTOR_PORT_ID, 2607 ACTION_NEXT, 2608 ZERO, 2609 }; 2610 2611 static const enum index action_represented_port[] = { 2612 ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID, 2613 ACTION_NEXT, 2614 ZERO, 2615 }; 2616 2617 static const enum index action_nat64[] = { 2618 ACTION_NAT64_MODE, 2619 ACTION_NEXT, 2620 ZERO, 2621 }; 2622 2623 static const enum index next_hash_subcmd[] = { 2624 HASH_CALC_TABLE, 2625 HASH_CALC_ENCAP, 2626 ZERO, 2627 }; 2628 2629 static const enum index next_hash_encap_dest_subcmd[] = { 2630 ENCAP_HASH_FIELD_SRC_PORT, 2631 ENCAP_HASH_FIELD_GRE_FLOW_ID, 2632 ZERO, 2633 }; 2634 2635 static int parse_set_raw_encap_decap(struct context *, const struct token *, 2636 const char *, unsigned int, 2637 void *, unsigned int); 2638 static int parse_set_sample_action(struct context *, const struct token *, 2639 const char *, unsigned int, 2640 void *, unsigned int); 2641 static int parse_set_ipv6_ext_action(struct context *, const struct token *, 2642 const char *, unsigned int, 2643 void *, unsigned int); 2644 static int parse_set_init(struct context *, const struct token *, 2645 const char *, unsigned int, 2646 void *, unsigned int); 2647 static int 2648 parse_flex_handle(struct context *, const struct token *, 2649 const char *, unsigned int, void *, unsigned int); 2650 static int parse_init(struct context *, const struct token *, 2651 const char *, unsigned int, 2652 void *, unsigned int); 2653 static int parse_vc(struct context *, const struct token *, 2654 const char *, unsigned int, 2655 void *, unsigned int); 2656 static int parse_vc_spec(struct context *, const struct token *, 2657 const char *, unsigned int, void *, unsigned int); 2658 static int parse_vc_conf(struct context *, const struct token *, 2659 const char *, unsigned int, void *, unsigned int); 2660 static int parse_vc_conf_timeout(struct context *, const struct token *, 2661 const char *, unsigned int, void *, 2662 unsigned int); 2663 static int parse_vc_item_ecpri_type(struct context *, const struct token *, 2664 const char *, unsigned int, 2665 void *, unsigned int); 2666 static int parse_vc_item_l2tpv2_type(struct context *, const struct token *, 2667 const char *, unsigned int, 2668 void *, unsigned int); 2669 static int parse_vc_action_meter_color_type(struct context *, 2670 const struct token *, 2671 const char *, unsigned int, void *, 2672 unsigned int); 2673 static int parse_vc_action_rss(struct context *, const struct token *, 2674 const char *, unsigned int, void *, 2675 unsigned int); 2676 static int parse_vc_action_rss_func(struct context *, const struct token *, 2677 const char *, unsigned int, void *, 2678 unsigned int); 2679 static int parse_vc_action_rss_type(struct context *, const struct token *, 2680 const char *, unsigned int, void *, 2681 unsigned int); 2682 static int parse_vc_action_rss_queue(struct context *, const struct token *, 2683 const char *, unsigned int, void *, 2684 unsigned int); 2685 static int parse_vc_action_vxlan_encap(struct context *, const struct token *, 2686 const char *, unsigned int, void *, 2687 unsigned int); 2688 static int parse_vc_action_nvgre_encap(struct context *, const struct token *, 2689 const char *, unsigned int, void *, 2690 unsigned int); 2691 static int parse_vc_action_l2_encap(struct context *, const struct token *, 2692 const char *, unsigned int, void *, 2693 unsigned int); 2694 static int parse_vc_action_l2_decap(struct context *, const struct token *, 2695 const char *, unsigned int, void *, 2696 unsigned int); 2697 static int parse_vc_action_mplsogre_encap(struct context *, 2698 const struct token *, const char *, 2699 unsigned int, void *, unsigned int); 2700 static int parse_vc_action_mplsogre_decap(struct context *, 2701 const struct token *, const char *, 2702 unsigned int, void *, unsigned int); 2703 static int parse_vc_action_mplsoudp_encap(struct context *, 2704 const struct token *, const char *, 2705 unsigned int, void *, unsigned int); 2706 static int parse_vc_action_mplsoudp_decap(struct context *, 2707 const struct token *, const char *, 2708 unsigned int, void *, unsigned int); 2709 static int parse_vc_action_raw_encap(struct context *, 2710 const struct token *, const char *, 2711 unsigned int, void *, unsigned int); 2712 static int parse_vc_action_raw_decap(struct context *, 2713 const struct token *, const char *, 2714 unsigned int, void *, unsigned int); 2715 static int parse_vc_action_raw_encap_index(struct context *, 2716 const struct token *, const char *, 2717 unsigned int, void *, unsigned int); 2718 static int parse_vc_action_raw_decap_index(struct context *, 2719 const struct token *, const char *, 2720 unsigned int, void *, unsigned int); 2721 static int parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token, 2722 const char *str, unsigned int len, void *buf, 2723 unsigned int size); 2724 static int parse_vc_action_ipv6_ext_remove_index(struct context *ctx, 2725 const struct token *token, 2726 const char *str, unsigned int len, 2727 void *buf, 2728 unsigned int size); 2729 static int parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token, 2730 const char *str, unsigned int len, void *buf, 2731 unsigned int size); 2732 static int parse_vc_action_ipv6_ext_push_index(struct context *ctx, 2733 const struct token *token, 2734 const char *str, unsigned int len, 2735 void *buf, 2736 unsigned int size); 2737 static int parse_vc_action_set_meta(struct context *ctx, 2738 const struct token *token, const char *str, 2739 unsigned int len, void *buf, 2740 unsigned int size); 2741 static int parse_vc_action_sample(struct context *ctx, 2742 const struct token *token, const char *str, 2743 unsigned int len, void *buf, 2744 unsigned int size); 2745 static int 2746 parse_vc_action_sample_index(struct context *ctx, const struct token *token, 2747 const char *str, unsigned int len, void *buf, 2748 unsigned int size); 2749 static int 2750 parse_vc_modify_field_op(struct context *ctx, const struct token *token, 2751 const char *str, unsigned int len, void *buf, 2752 unsigned int size); 2753 static int 2754 parse_vc_modify_field_id(struct context *ctx, const struct token *token, 2755 const char *str, unsigned int len, void *buf, 2756 unsigned int size); 2757 static int 2758 parse_vc_modify_field_level(struct context *ctx, const struct token *token, 2759 const char *str, unsigned int len, void *buf, 2760 unsigned int size); 2761 static int 2762 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token, 2763 const char *str, unsigned int len, void *buf, 2764 unsigned int size); 2765 static int parse_destroy(struct context *, const struct token *, 2766 const char *, unsigned int, 2767 void *, unsigned int); 2768 static int parse_flush(struct context *, const struct token *, 2769 const char *, unsigned int, 2770 void *, unsigned int); 2771 static int parse_dump(struct context *, const struct token *, 2772 const char *, unsigned int, 2773 void *, unsigned int); 2774 static int parse_query(struct context *, const struct token *, 2775 const char *, unsigned int, 2776 void *, unsigned int); 2777 static int parse_action(struct context *, const struct token *, 2778 const char *, unsigned int, 2779 void *, unsigned int); 2780 static int parse_list(struct context *, const struct token *, 2781 const char *, unsigned int, 2782 void *, unsigned int); 2783 static int parse_aged(struct context *, const struct token *, 2784 const char *, unsigned int, 2785 void *, unsigned int); 2786 static int parse_isolate(struct context *, const struct token *, 2787 const char *, unsigned int, 2788 void *, unsigned int); 2789 static int parse_configure(struct context *, const struct token *, 2790 const char *, unsigned int, 2791 void *, unsigned int); 2792 static int parse_template(struct context *, const struct token *, 2793 const char *, unsigned int, 2794 void *, unsigned int); 2795 static int parse_template_destroy(struct context *, const struct token *, 2796 const char *, unsigned int, 2797 void *, unsigned int); 2798 static int parse_table(struct context *, const struct token *, 2799 const char *, unsigned int, void *, unsigned int); 2800 static int parse_table_destroy(struct context *, const struct token *, 2801 const char *, unsigned int, 2802 void *, unsigned int); 2803 static int parse_qo(struct context *, const struct token *, 2804 const char *, unsigned int, 2805 void *, unsigned int); 2806 static int parse_qo_destroy(struct context *, const struct token *, 2807 const char *, unsigned int, 2808 void *, unsigned int); 2809 static int parse_qia(struct context *, const struct token *, 2810 const char *, unsigned int, 2811 void *, unsigned int); 2812 static int parse_qia_destroy(struct context *, const struct token *, 2813 const char *, unsigned int, 2814 void *, unsigned int); 2815 static int parse_push(struct context *, const struct token *, 2816 const char *, unsigned int, 2817 void *, unsigned int); 2818 static int parse_pull(struct context *, const struct token *, 2819 const char *, unsigned int, 2820 void *, unsigned int); 2821 static int parse_group(struct context *, const struct token *, 2822 const char *, unsigned int, 2823 void *, unsigned int); 2824 static int parse_hash(struct context *, const struct token *, 2825 const char *, unsigned int, 2826 void *, unsigned int); 2827 static int parse_tunnel(struct context *, const struct token *, 2828 const char *, unsigned int, 2829 void *, unsigned int); 2830 static int parse_flex(struct context *, const struct token *, 2831 const char *, unsigned int, void *, unsigned int); 2832 static int parse_int(struct context *, const struct token *, 2833 const char *, unsigned int, 2834 void *, unsigned int); 2835 static int parse_prefix(struct context *, const struct token *, 2836 const char *, unsigned int, 2837 void *, unsigned int); 2838 static int parse_boolean(struct context *, const struct token *, 2839 const char *, unsigned int, 2840 void *, unsigned int); 2841 static int parse_string(struct context *, const struct token *, 2842 const char *, unsigned int, 2843 void *, unsigned int); 2844 static int parse_hex(struct context *ctx, const struct token *token, 2845 const char *str, unsigned int len, 2846 void *buf, unsigned int size); 2847 static int parse_string0(struct context *, const struct token *, 2848 const char *, unsigned int, 2849 void *, unsigned int); 2850 static int parse_mac_addr(struct context *, const struct token *, 2851 const char *, unsigned int, 2852 void *, unsigned int); 2853 static int parse_ipv4_addr(struct context *, const struct token *, 2854 const char *, unsigned int, 2855 void *, unsigned int); 2856 static int parse_ipv6_addr(struct context *, const struct token *, 2857 const char *, unsigned int, 2858 void *, unsigned int); 2859 static int parse_port(struct context *, const struct token *, 2860 const char *, unsigned int, 2861 void *, unsigned int); 2862 static int parse_ia(struct context *, const struct token *, 2863 const char *, unsigned int, 2864 void *, unsigned int); 2865 static int parse_ia_destroy(struct context *ctx, const struct token *token, 2866 const char *str, unsigned int len, 2867 void *buf, unsigned int size); 2868 static int parse_ia_id2ptr(struct context *ctx, const struct token *token, 2869 const char *str, unsigned int len, void *buf, 2870 unsigned int size); 2871 2872 static int parse_indlst_id2ptr(struct context *ctx, const struct token *token, 2873 const char *str, unsigned int len, void *buf, 2874 unsigned int size); 2875 static int parse_ia_port(struct context *ctx, const struct token *token, 2876 const char *str, unsigned int len, void *buf, 2877 unsigned int size); 2878 static int parse_mp(struct context *, const struct token *, 2879 const char *, unsigned int, 2880 void *, unsigned int); 2881 static int parse_meter_profile_id2ptr(struct context *ctx, 2882 const struct token *token, 2883 const char *str, unsigned int len, 2884 void *buf, unsigned int size); 2885 static int parse_meter_policy_id2ptr(struct context *ctx, 2886 const struct token *token, 2887 const char *str, unsigned int len, 2888 void *buf, unsigned int size); 2889 static int parse_meter_color(struct context *ctx, const struct token *token, 2890 const char *str, unsigned int len, void *buf, 2891 unsigned int size); 2892 static int parse_insertion_table_type(struct context *ctx, const struct token *token, 2893 const char *str, unsigned int len, void *buf, 2894 unsigned int size); 2895 static int parse_hash_table_type(struct context *ctx, const struct token *token, 2896 const char *str, unsigned int len, void *buf, 2897 unsigned int size); 2898 static int 2899 parse_quota_state_name(struct context *ctx, const struct token *token, 2900 const char *str, unsigned int len, void *buf, 2901 unsigned int size); 2902 static int 2903 parse_quota_mode_name(struct context *ctx, const struct token *token, 2904 const char *str, unsigned int len, void *buf, 2905 unsigned int size); 2906 static int 2907 parse_quota_update_name(struct context *ctx, const struct token *token, 2908 const char *str, unsigned int len, void *buf, 2909 unsigned int size); 2910 static int 2911 parse_qu_mode_name(struct context *ctx, const struct token *token, 2912 const char *str, unsigned int len, void *buf, 2913 unsigned int size); 2914 static int comp_none(struct context *, const struct token *, 2915 unsigned int, char *, unsigned int); 2916 static int comp_boolean(struct context *, const struct token *, 2917 unsigned int, char *, unsigned int); 2918 static int comp_action(struct context *, const struct token *, 2919 unsigned int, char *, unsigned int); 2920 static int comp_port(struct context *, const struct token *, 2921 unsigned int, char *, unsigned int); 2922 static int comp_rule_id(struct context *, const struct token *, 2923 unsigned int, char *, unsigned int); 2924 static int comp_vc_action_rss_type(struct context *, const struct token *, 2925 unsigned int, char *, unsigned int); 2926 static int comp_vc_action_rss_queue(struct context *, const struct token *, 2927 unsigned int, char *, unsigned int); 2928 static int comp_set_raw_index(struct context *, const struct token *, 2929 unsigned int, char *, unsigned int); 2930 static int comp_set_sample_index(struct context *, const struct token *, 2931 unsigned int, char *, unsigned int); 2932 static int comp_set_ipv6_ext_index(struct context *ctx, const struct token *token, 2933 unsigned int ent, char *buf, unsigned int size); 2934 static int comp_set_modify_field_op(struct context *, const struct token *, 2935 unsigned int, char *, unsigned int); 2936 static int comp_set_modify_field_id(struct context *, const struct token *, 2937 unsigned int, char *, unsigned int); 2938 static int comp_pattern_template_id(struct context *, const struct token *, 2939 unsigned int, char *, unsigned int); 2940 static int comp_actions_template_id(struct context *, const struct token *, 2941 unsigned int, char *, unsigned int); 2942 static int comp_table_id(struct context *, const struct token *, 2943 unsigned int, char *, unsigned int); 2944 static int comp_queue_id(struct context *, const struct token *, 2945 unsigned int, char *, unsigned int); 2946 static int comp_meter_color(struct context *, const struct token *, 2947 unsigned int, char *, unsigned int); 2948 static int comp_insertion_table_type(struct context *, const struct token *, 2949 unsigned int, char *, unsigned int); 2950 static int comp_hash_table_type(struct context *, const struct token *, 2951 unsigned int, char *, unsigned int); 2952 static int 2953 comp_quota_state_name(struct context *ctx, const struct token *token, 2954 unsigned int ent, char *buf, unsigned int size); 2955 static int 2956 comp_quota_mode_name(struct context *ctx, const struct token *token, 2957 unsigned int ent, char *buf, unsigned int size); 2958 static int 2959 comp_quota_update_name(struct context *ctx, const struct token *token, 2960 unsigned int ent, char *buf, unsigned int size); 2961 static int 2962 comp_qu_mode_name(struct context *ctx, const struct token *token, 2963 unsigned int ent, char *buf, unsigned int size); 2964 static int 2965 comp_set_compare_field_id(struct context *ctx, const struct token *token, 2966 unsigned int ent, char *buf, unsigned int size); 2967 static int 2968 comp_set_compare_op(struct context *ctx, const struct token *token, 2969 unsigned int ent, char *buf, unsigned int size); 2970 static int 2971 parse_vc_compare_op(struct context *ctx, const struct token *token, 2972 const char *str, unsigned int len, void *buf, 2973 unsigned int size); 2974 static int 2975 parse_vc_compare_field_id(struct context *ctx, const struct token *token, 2976 const char *str, unsigned int len, void *buf, 2977 unsigned int size); 2978 static int 2979 parse_vc_compare_field_level(struct context *ctx, const struct token *token, 2980 const char *str, unsigned int len, void *buf, 2981 unsigned int size); 2982 2983 struct indlst_conf { 2984 uint32_t id; 2985 uint32_t conf_num; 2986 struct rte_flow_action *actions; 2987 const void **conf; 2988 SLIST_ENTRY(indlst_conf) next; 2989 }; 2990 2991 static const struct indlst_conf *indirect_action_list_conf_get(uint32_t conf_id); 2992 2993 /** Token definitions. */ 2994 static const struct token token_list[] = { 2995 /* Special tokens. */ 2996 [ZERO] = { 2997 .name = "ZERO", 2998 .help = "null entry, abused as the entry point", 2999 .next = NEXT(NEXT_ENTRY(FLOW, ADD)), 3000 }, 3001 [END] = { 3002 .name = "", 3003 .type = "RETURN", 3004 .help = "command may end here", 3005 }, 3006 [START_SET] = { 3007 .name = "START_SET", 3008 .help = "null entry, abused as the entry point for set", 3009 .next = NEXT(NEXT_ENTRY(SET)), 3010 }, 3011 [END_SET] = { 3012 .name = "end_set", 3013 .type = "RETURN", 3014 .help = "set command may end here", 3015 }, 3016 /* Common tokens. */ 3017 [COMMON_INTEGER] = { 3018 .name = "{int}", 3019 .type = "INTEGER", 3020 .help = "integer value", 3021 .call = parse_int, 3022 .comp = comp_none, 3023 }, 3024 [COMMON_UNSIGNED] = { 3025 .name = "{unsigned}", 3026 .type = "UNSIGNED", 3027 .help = "unsigned integer value", 3028 .call = parse_int, 3029 .comp = comp_none, 3030 }, 3031 [COMMON_PREFIX] = { 3032 .name = "{prefix}", 3033 .type = "PREFIX", 3034 .help = "prefix length for bit-mask", 3035 .call = parse_prefix, 3036 .comp = comp_none, 3037 }, 3038 [COMMON_BOOLEAN] = { 3039 .name = "{boolean}", 3040 .type = "BOOLEAN", 3041 .help = "any boolean value", 3042 .call = parse_boolean, 3043 .comp = comp_boolean, 3044 }, 3045 [COMMON_STRING] = { 3046 .name = "{string}", 3047 .type = "STRING", 3048 .help = "fixed string", 3049 .call = parse_string, 3050 .comp = comp_none, 3051 }, 3052 [COMMON_HEX] = { 3053 .name = "{hex}", 3054 .type = "HEX", 3055 .help = "fixed string", 3056 .call = parse_hex, 3057 }, 3058 [COMMON_FILE_PATH] = { 3059 .name = "{file path}", 3060 .type = "STRING", 3061 .help = "file path", 3062 .call = parse_string0, 3063 .comp = comp_none, 3064 }, 3065 [COMMON_MAC_ADDR] = { 3066 .name = "{MAC address}", 3067 .type = "MAC-48", 3068 .help = "standard MAC address notation", 3069 .call = parse_mac_addr, 3070 .comp = comp_none, 3071 }, 3072 [COMMON_IPV4_ADDR] = { 3073 .name = "{IPv4 address}", 3074 .type = "IPV4 ADDRESS", 3075 .help = "standard IPv4 address notation", 3076 .call = parse_ipv4_addr, 3077 .comp = comp_none, 3078 }, 3079 [COMMON_IPV6_ADDR] = { 3080 .name = "{IPv6 address}", 3081 .type = "IPV6 ADDRESS", 3082 .help = "standard IPv6 address notation", 3083 .call = parse_ipv6_addr, 3084 .comp = comp_none, 3085 }, 3086 [COMMON_RULE_ID] = { 3087 .name = "{rule id}", 3088 .type = "RULE ID", 3089 .help = "rule identifier", 3090 .call = parse_int, 3091 .comp = comp_rule_id, 3092 }, 3093 [COMMON_PORT_ID] = { 3094 .name = "{port_id}", 3095 .type = "PORT ID", 3096 .help = "port identifier", 3097 .call = parse_port, 3098 .comp = comp_port, 3099 }, 3100 [COMMON_GROUP_ID] = { 3101 .name = "{group_id}", 3102 .type = "GROUP ID", 3103 .help = "group identifier", 3104 .call = parse_int, 3105 .comp = comp_none, 3106 }, 3107 [COMMON_PRIORITY_LEVEL] = { 3108 .name = "{level}", 3109 .type = "PRIORITY", 3110 .help = "priority level", 3111 .call = parse_int, 3112 .comp = comp_none, 3113 }, 3114 [COMMON_INDIRECT_ACTION_ID] = { 3115 .name = "{indirect_action_id}", 3116 .type = "INDIRECT_ACTION_ID", 3117 .help = "indirect action id", 3118 .call = parse_int, 3119 .comp = comp_none, 3120 }, 3121 [COMMON_PROFILE_ID] = { 3122 .name = "{profile_id}", 3123 .type = "PROFILE_ID", 3124 .help = "profile id", 3125 .call = parse_int, 3126 .comp = comp_none, 3127 }, 3128 [COMMON_POLICY_ID] = { 3129 .name = "{policy_id}", 3130 .type = "POLICY_ID", 3131 .help = "policy id", 3132 .call = parse_int, 3133 .comp = comp_none, 3134 }, 3135 [COMMON_FLEX_TOKEN] = { 3136 .name = "{flex token}", 3137 .type = "flex token", 3138 .help = "flex token", 3139 .call = parse_int, 3140 .comp = comp_none, 3141 }, 3142 [COMMON_FLEX_HANDLE] = { 3143 .name = "{flex handle}", 3144 .type = "FLEX HANDLE", 3145 .help = "fill flex item data", 3146 .call = parse_flex_handle, 3147 .comp = comp_none, 3148 }, 3149 [COMMON_PATTERN_TEMPLATE_ID] = { 3150 .name = "{pattern_template_id}", 3151 .type = "PATTERN_TEMPLATE_ID", 3152 .help = "pattern template id", 3153 .call = parse_int, 3154 .comp = comp_pattern_template_id, 3155 }, 3156 [COMMON_ACTIONS_TEMPLATE_ID] = { 3157 .name = "{actions_template_id}", 3158 .type = "ACTIONS_TEMPLATE_ID", 3159 .help = "actions template id", 3160 .call = parse_int, 3161 .comp = comp_actions_template_id, 3162 }, 3163 [COMMON_TABLE_ID] = { 3164 .name = "{table_id}", 3165 .type = "TABLE_ID", 3166 .help = "table id", 3167 .call = parse_int, 3168 .comp = comp_table_id, 3169 }, 3170 [COMMON_QUEUE_ID] = { 3171 .name = "{queue_id}", 3172 .type = "QUEUE_ID", 3173 .help = "queue id", 3174 .call = parse_int, 3175 .comp = comp_queue_id, 3176 }, 3177 /* Top-level command. */ 3178 [FLOW] = { 3179 .name = "flow", 3180 .type = "{command} {port_id} [{arg} [...]]", 3181 .help = "manage ingress/egress flow rules", 3182 .next = NEXT(NEXT_ENTRY 3183 (INFO, 3184 CONFIGURE, 3185 PATTERN_TEMPLATE, 3186 ACTIONS_TEMPLATE, 3187 TABLE, 3188 FLOW_GROUP, 3189 INDIRECT_ACTION, 3190 VALIDATE, 3191 CREATE, 3192 DESTROY, 3193 FLUSH, 3194 DUMP, 3195 LIST, 3196 AGED, 3197 QUERY, 3198 ISOLATE, 3199 TUNNEL, 3200 FLEX, 3201 QUEUE, 3202 PUSH, 3203 PULL, 3204 HASH)), 3205 .call = parse_init, 3206 }, 3207 /* Top-level command. */ 3208 [INFO] = { 3209 .name = "info", 3210 .help = "get information about flow engine", 3211 .next = NEXT(NEXT_ENTRY(END), 3212 NEXT_ENTRY(COMMON_PORT_ID)), 3213 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3214 .call = parse_configure, 3215 }, 3216 /* Top-level command. */ 3217 [CONFIGURE] = { 3218 .name = "configure", 3219 .help = "configure flow engine", 3220 .next = NEXT(next_config_attr, 3221 NEXT_ENTRY(COMMON_PORT_ID)), 3222 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3223 .call = parse_configure, 3224 }, 3225 /* Configure arguments. */ 3226 [CONFIG_QUEUES_NUMBER] = { 3227 .name = "queues_number", 3228 .help = "number of queues", 3229 .next = NEXT(next_config_attr, 3230 NEXT_ENTRY(COMMON_UNSIGNED)), 3231 .args = ARGS(ARGS_ENTRY(struct buffer, 3232 args.configure.nb_queue)), 3233 }, 3234 [CONFIG_QUEUES_SIZE] = { 3235 .name = "queues_size", 3236 .help = "number of elements in queues", 3237 .next = NEXT(next_config_attr, 3238 NEXT_ENTRY(COMMON_UNSIGNED)), 3239 .args = ARGS(ARGS_ENTRY(struct buffer, 3240 args.configure.queue_attr.size)), 3241 }, 3242 [CONFIG_COUNTERS_NUMBER] = { 3243 .name = "counters_number", 3244 .help = "number of counters", 3245 .next = NEXT(next_config_attr, 3246 NEXT_ENTRY(COMMON_UNSIGNED)), 3247 .args = ARGS(ARGS_ENTRY(struct buffer, 3248 args.configure.port_attr.nb_counters)), 3249 }, 3250 [CONFIG_AGING_OBJECTS_NUMBER] = { 3251 .name = "aging_counters_number", 3252 .help = "number of aging objects", 3253 .next = NEXT(next_config_attr, 3254 NEXT_ENTRY(COMMON_UNSIGNED)), 3255 .args = ARGS(ARGS_ENTRY(struct buffer, 3256 args.configure.port_attr.nb_aging_objects)), 3257 }, 3258 [CONFIG_QUOTAS_NUMBER] = { 3259 .name = "quotas_number", 3260 .help = "number of quotas", 3261 .next = NEXT(next_config_attr, 3262 NEXT_ENTRY(COMMON_UNSIGNED)), 3263 .args = ARGS(ARGS_ENTRY(struct buffer, 3264 args.configure.port_attr.nb_quotas)), 3265 }, 3266 [CONFIG_METERS_NUMBER] = { 3267 .name = "meters_number", 3268 .help = "number of meters", 3269 .next = NEXT(next_config_attr, 3270 NEXT_ENTRY(COMMON_UNSIGNED)), 3271 .args = ARGS(ARGS_ENTRY(struct buffer, 3272 args.configure.port_attr.nb_meters)), 3273 }, 3274 [CONFIG_CONN_TRACK_NUMBER] = { 3275 .name = "conn_tracks_number", 3276 .help = "number of connection trackings", 3277 .next = NEXT(next_config_attr, 3278 NEXT_ENTRY(COMMON_UNSIGNED)), 3279 .args = ARGS(ARGS_ENTRY(struct buffer, 3280 args.configure.port_attr.nb_conn_tracks)), 3281 }, 3282 [CONFIG_FLAGS] = { 3283 .name = "flags", 3284 .help = "configuration flags", 3285 .next = NEXT(next_config_attr, 3286 NEXT_ENTRY(COMMON_UNSIGNED)), 3287 .args = ARGS(ARGS_ENTRY(struct buffer, 3288 args.configure.port_attr.flags)), 3289 }, 3290 [CONFIG_HOST_PORT] = { 3291 .name = "host_port", 3292 .help = "host port for shared objects", 3293 .next = NEXT(next_config_attr, 3294 NEXT_ENTRY(COMMON_UNSIGNED)), 3295 .args = ARGS(ARGS_ENTRY(struct buffer, 3296 args.configure.port_attr.host_port_id)), 3297 }, 3298 /* Top-level command. */ 3299 [PATTERN_TEMPLATE] = { 3300 .name = "pattern_template", 3301 .type = "{command} {port_id} [{arg} [...]]", 3302 .help = "manage pattern templates", 3303 .next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), 3304 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3305 .call = parse_template, 3306 }, 3307 /* Sub-level commands. */ 3308 [PATTERN_TEMPLATE_CREATE] = { 3309 .name = "create", 3310 .help = "create pattern template", 3311 .next = NEXT(next_pt_attr), 3312 .call = parse_template, 3313 }, 3314 [PATTERN_TEMPLATE_DESTROY] = { 3315 .name = "destroy", 3316 .help = "destroy pattern template", 3317 .next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)), 3318 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3319 .call = parse_template_destroy, 3320 }, 3321 /* Pattern template arguments. */ 3322 [PATTERN_TEMPLATE_CREATE_ID] = { 3323 .name = "pattern_template_id", 3324 .help = "specify a pattern template id to create", 3325 .next = NEXT(next_pt_attr, 3326 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)), 3327 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)), 3328 }, 3329 [PATTERN_TEMPLATE_DESTROY_ID] = { 3330 .name = "pattern_template", 3331 .help = "specify a pattern template id to destroy", 3332 .next = NEXT(next_pt_destroy_attr, 3333 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)), 3334 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, 3335 args.templ_destroy.template_id)), 3336 .call = parse_template_destroy, 3337 }, 3338 [PATTERN_TEMPLATE_RELAXED_MATCHING] = { 3339 .name = "relaxed", 3340 .help = "is matching relaxed", 3341 .next = NEXT(next_pt_attr, 3342 NEXT_ENTRY(COMMON_BOOLEAN)), 3343 .args = ARGS(ARGS_ENTRY_BF(struct buffer, 3344 args.vc.attr.reserved, 1)), 3345 }, 3346 [PATTERN_TEMPLATE_INGRESS] = { 3347 .name = "ingress", 3348 .help = "attribute pattern to ingress", 3349 .next = NEXT(next_pt_attr), 3350 .call = parse_template, 3351 }, 3352 [PATTERN_TEMPLATE_EGRESS] = { 3353 .name = "egress", 3354 .help = "attribute pattern to egress", 3355 .next = NEXT(next_pt_attr), 3356 .call = parse_template, 3357 }, 3358 [PATTERN_TEMPLATE_TRANSFER] = { 3359 .name = "transfer", 3360 .help = "attribute pattern to transfer", 3361 .next = NEXT(next_pt_attr), 3362 .call = parse_template, 3363 }, 3364 [PATTERN_TEMPLATE_SPEC] = { 3365 .name = "template", 3366 .help = "specify item to create pattern template", 3367 .next = NEXT(next_item), 3368 }, 3369 /* Top-level command. */ 3370 [ACTIONS_TEMPLATE] = { 3371 .name = "actions_template", 3372 .type = "{command} {port_id} [{arg} [...]]", 3373 .help = "manage actions templates", 3374 .next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), 3375 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3376 .call = parse_template, 3377 }, 3378 /* Sub-level commands. */ 3379 [ACTIONS_TEMPLATE_CREATE] = { 3380 .name = "create", 3381 .help = "create actions template", 3382 .next = NEXT(next_at_attr), 3383 .call = parse_template, 3384 }, 3385 [ACTIONS_TEMPLATE_DESTROY] = { 3386 .name = "destroy", 3387 .help = "destroy actions template", 3388 .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)), 3389 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3390 .call = parse_template_destroy, 3391 }, 3392 /* Actions template arguments. */ 3393 [ACTIONS_TEMPLATE_CREATE_ID] = { 3394 .name = "actions_template_id", 3395 .help = "specify an actions template id to create", 3396 .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK), 3397 NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC), 3398 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)), 3399 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)), 3400 }, 3401 [ACTIONS_TEMPLATE_DESTROY_ID] = { 3402 .name = "actions_template", 3403 .help = "specify an actions template id to destroy", 3404 .next = NEXT(next_at_destroy_attr, 3405 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)), 3406 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, 3407 args.templ_destroy.template_id)), 3408 .call = parse_template_destroy, 3409 }, 3410 [ACTIONS_TEMPLATE_INGRESS] = { 3411 .name = "ingress", 3412 .help = "attribute actions to ingress", 3413 .next = NEXT(next_at_attr), 3414 .call = parse_template, 3415 }, 3416 [ACTIONS_TEMPLATE_EGRESS] = { 3417 .name = "egress", 3418 .help = "attribute actions to egress", 3419 .next = NEXT(next_at_attr), 3420 .call = parse_template, 3421 }, 3422 [ACTIONS_TEMPLATE_TRANSFER] = { 3423 .name = "transfer", 3424 .help = "attribute actions to transfer", 3425 .next = NEXT(next_at_attr), 3426 .call = parse_template, 3427 }, 3428 [ACTIONS_TEMPLATE_SPEC] = { 3429 .name = "template", 3430 .help = "specify action to create actions template", 3431 .next = NEXT(next_action), 3432 .call = parse_template, 3433 }, 3434 [ACTIONS_TEMPLATE_MASK] = { 3435 .name = "mask", 3436 .help = "specify action mask to create actions template", 3437 .next = NEXT(next_action), 3438 .call = parse_template, 3439 }, 3440 /* Top-level command. */ 3441 [TABLE] = { 3442 .name = "template_table", 3443 .type = "{command} {port_id} [{arg} [...]]", 3444 .help = "manage template tables", 3445 .next = NEXT(next_table_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), 3446 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3447 .call = parse_table, 3448 }, 3449 /* Sub-level commands. */ 3450 [TABLE_CREATE] = { 3451 .name = "create", 3452 .help = "create template table", 3453 .next = NEXT(next_table_attr), 3454 .call = parse_table, 3455 }, 3456 [TABLE_DESTROY] = { 3457 .name = "destroy", 3458 .help = "destroy template table", 3459 .next = NEXT(NEXT_ENTRY(TABLE_DESTROY_ID)), 3460 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3461 .call = parse_table_destroy, 3462 }, 3463 /* Table arguments. */ 3464 [TABLE_CREATE_ID] = { 3465 .name = "table_id", 3466 .help = "specify table id to create", 3467 .next = NEXT(next_table_attr, 3468 NEXT_ENTRY(COMMON_TABLE_ID)), 3469 .args = ARGS(ARGS_ENTRY(struct buffer, args.table.id)), 3470 }, 3471 [TABLE_DESTROY_ID] = { 3472 .name = "table", 3473 .help = "specify table id to destroy", 3474 .next = NEXT(next_table_destroy_attr, 3475 NEXT_ENTRY(COMMON_TABLE_ID)), 3476 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, 3477 args.table_destroy.table_id)), 3478 .call = parse_table_destroy, 3479 }, 3480 [TABLE_INSERTION_TYPE] = { 3481 .name = "insertion_type", 3482 .help = "specify insertion type", 3483 .next = NEXT(next_table_attr, 3484 NEXT_ENTRY(TABLE_INSERTION_TYPE_NAME)), 3485 .args = ARGS(ARGS_ENTRY(struct buffer, 3486 args.table.attr.insertion_type)), 3487 }, 3488 [TABLE_INSERTION_TYPE_NAME] = { 3489 .name = "insertion_type_name", 3490 .help = "insertion type name", 3491 .call = parse_insertion_table_type, 3492 .comp = comp_insertion_table_type, 3493 }, 3494 [TABLE_HASH_FUNC] = { 3495 .name = "hash_func", 3496 .help = "specify hash calculation function", 3497 .next = NEXT(next_table_attr, 3498 NEXT_ENTRY(TABLE_HASH_FUNC_NAME)), 3499 .args = ARGS(ARGS_ENTRY(struct buffer, 3500 args.table.attr.hash_func)), 3501 }, 3502 [TABLE_HASH_FUNC_NAME] = { 3503 .name = "hash_func_name", 3504 .help = "hash calculation function name", 3505 .call = parse_hash_table_type, 3506 .comp = comp_hash_table_type, 3507 }, 3508 [TABLE_GROUP] = { 3509 .name = "group", 3510 .help = "specify a group", 3511 .next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_GROUP_ID)), 3512 .args = ARGS(ARGS_ENTRY(struct buffer, 3513 args.table.attr.flow_attr.group)), 3514 }, 3515 [TABLE_PRIORITY] = { 3516 .name = "priority", 3517 .help = "specify a priority level", 3518 .next = NEXT(next_table_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)), 3519 .args = ARGS(ARGS_ENTRY(struct buffer, 3520 args.table.attr.flow_attr.priority)), 3521 }, 3522 [TABLE_EGRESS] = { 3523 .name = "egress", 3524 .help = "affect rule to egress", 3525 .next = NEXT(next_table_attr), 3526 .call = parse_table, 3527 }, 3528 [TABLE_INGRESS] = { 3529 .name = "ingress", 3530 .help = "affect rule to ingress", 3531 .next = NEXT(next_table_attr), 3532 .call = parse_table, 3533 }, 3534 [TABLE_TRANSFER] = { 3535 .name = "transfer", 3536 .help = "affect rule to transfer", 3537 .next = NEXT(next_table_attr), 3538 .call = parse_table, 3539 }, 3540 [TABLE_TRANSFER_WIRE_ORIG] = { 3541 .name = "wire_orig", 3542 .help = "affect rule direction to transfer", 3543 .next = NEXT(next_table_attr), 3544 .call = parse_table, 3545 }, 3546 [TABLE_TRANSFER_VPORT_ORIG] = { 3547 .name = "vport_orig", 3548 .help = "affect rule direction to transfer", 3549 .next = NEXT(next_table_attr), 3550 .call = parse_table, 3551 }, 3552 [TABLE_RULES_NUMBER] = { 3553 .name = "rules_number", 3554 .help = "number of rules in table", 3555 .next = NEXT(next_table_attr, 3556 NEXT_ENTRY(COMMON_UNSIGNED)), 3557 .args = ARGS(ARGS_ENTRY(struct buffer, 3558 args.table.attr.nb_flows)), 3559 .call = parse_table, 3560 }, 3561 [TABLE_PATTERN_TEMPLATE] = { 3562 .name = "pattern_template", 3563 .help = "specify pattern template id", 3564 .next = NEXT(next_table_attr, 3565 NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)), 3566 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, 3567 args.table.pat_templ_id)), 3568 .call = parse_table, 3569 }, 3570 [TABLE_ACTIONS_TEMPLATE] = { 3571 .name = "actions_template", 3572 .help = "specify actions template id", 3573 .next = NEXT(next_table_attr, 3574 NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)), 3575 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, 3576 args.table.act_templ_id)), 3577 .call = parse_table, 3578 }, 3579 /* Top-level command. */ 3580 [FLOW_GROUP] = { 3581 .name = "group", 3582 .help = "manage flow groups", 3583 .next = NEXT(NEXT_ENTRY(GROUP_ID), NEXT_ENTRY(COMMON_PORT_ID)), 3584 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3585 .call = parse_group, 3586 }, 3587 /* Sub-level commands. */ 3588 [GROUP_SET_MISS_ACTIONS] = { 3589 .name = "set_miss_actions", 3590 .help = "set group miss actions", 3591 .next = NEXT(next_action), 3592 .call = parse_group, 3593 }, 3594 /* Group arguments */ 3595 [GROUP_ID] = { 3596 .name = "group_id", 3597 .help = "group id", 3598 .next = NEXT(next_group_attr, NEXT_ENTRY(COMMON_GROUP_ID)), 3599 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)), 3600 }, 3601 [GROUP_INGRESS] = { 3602 .name = "ingress", 3603 .help = "group ingress attr", 3604 .next = NEXT(next_group_attr), 3605 .call = parse_group, 3606 }, 3607 [GROUP_EGRESS] = { 3608 .name = "egress", 3609 .help = "group egress attr", 3610 .next = NEXT(next_group_attr), 3611 .call = parse_group, 3612 }, 3613 [GROUP_TRANSFER] = { 3614 .name = "transfer", 3615 .help = "group transfer attr", 3616 .next = NEXT(next_group_attr), 3617 .call = parse_group, 3618 }, 3619 /* Top-level command. */ 3620 [QUEUE] = { 3621 .name = "queue", 3622 .help = "queue a flow rule operation", 3623 .next = NEXT(next_queue_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), 3624 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3625 .call = parse_qo, 3626 }, 3627 /* Sub-level commands. */ 3628 [QUEUE_CREATE] = { 3629 .name = "create", 3630 .help = "create a flow rule", 3631 .next = NEXT(NEXT_ENTRY(QUEUE_TEMPLATE_TABLE), 3632 NEXT_ENTRY(COMMON_QUEUE_ID)), 3633 .args = ARGS(ARGS_ENTRY(struct buffer, queue)), 3634 .call = parse_qo, 3635 }, 3636 [QUEUE_DESTROY] = { 3637 .name = "destroy", 3638 .help = "destroy a flow rule", 3639 .next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID), 3640 NEXT_ENTRY(COMMON_QUEUE_ID)), 3641 .args = ARGS(ARGS_ENTRY(struct buffer, queue)), 3642 .call = parse_qo_destroy, 3643 }, 3644 [QUEUE_UPDATE] = { 3645 .name = "update", 3646 .help = "update a flow rule", 3647 .next = NEXT(NEXT_ENTRY(QUEUE_UPDATE_ID), 3648 NEXT_ENTRY(COMMON_QUEUE_ID)), 3649 .args = ARGS(ARGS_ENTRY(struct buffer, queue)), 3650 .call = parse_qo, 3651 }, 3652 [QUEUE_AGED] = { 3653 .name = "aged", 3654 .help = "list and destroy aged flows", 3655 .next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_QUEUE_ID)), 3656 .args = ARGS(ARGS_ENTRY(struct buffer, queue)), 3657 .call = parse_aged, 3658 }, 3659 [QUEUE_INDIRECT_ACTION] = { 3660 .name = "indirect_action", 3661 .help = "queue indirect actions", 3662 .next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)), 3663 .args = ARGS(ARGS_ENTRY(struct buffer, queue)), 3664 .call = parse_qia, 3665 }, 3666 /* Queue arguments. */ 3667 [QUEUE_TEMPLATE_TABLE] = { 3668 .name = "template_table", 3669 .help = "specify table id", 3670 .next = NEXT(next_async_insert_subcmd, 3671 NEXT_ENTRY(COMMON_TABLE_ID)), 3672 .args = ARGS(ARGS_ENTRY(struct buffer, 3673 args.vc.table_id)), 3674 .call = parse_qo, 3675 }, 3676 [QUEUE_PATTERN_TEMPLATE] = { 3677 .name = "pattern_template", 3678 .help = "specify pattern template index", 3679 .next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE), 3680 NEXT_ENTRY(COMMON_UNSIGNED)), 3681 .args = ARGS(ARGS_ENTRY(struct buffer, 3682 args.vc.pat_templ_id)), 3683 .call = parse_qo, 3684 }, 3685 [QUEUE_ACTIONS_TEMPLATE] = { 3686 .name = "actions_template", 3687 .help = "specify actions template index", 3688 .next = NEXT(NEXT_ENTRY(QUEUE_CREATE_POSTPONE), 3689 NEXT_ENTRY(COMMON_UNSIGNED)), 3690 .args = ARGS(ARGS_ENTRY(struct buffer, 3691 args.vc.act_templ_id)), 3692 .call = parse_qo, 3693 }, 3694 [QUEUE_RULE_ID] = { 3695 .name = "rule_index", 3696 .help = "specify flow rule index", 3697 .next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE), 3698 NEXT_ENTRY(COMMON_UNSIGNED)), 3699 .args = ARGS(ARGS_ENTRY(struct buffer, 3700 args.vc.rule_id)), 3701 .call = parse_qo, 3702 }, 3703 [QUEUE_CREATE_POSTPONE] = { 3704 .name = "postpone", 3705 .help = "postpone create operation", 3706 .next = NEXT(NEXT_ENTRY(ITEM_PATTERN), 3707 NEXT_ENTRY(COMMON_BOOLEAN)), 3708 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)), 3709 .call = parse_qo, 3710 }, 3711 [QUEUE_DESTROY_POSTPONE] = { 3712 .name = "postpone", 3713 .help = "postpone destroy operation", 3714 .next = NEXT(NEXT_ENTRY(QUEUE_DESTROY_ID), 3715 NEXT_ENTRY(COMMON_BOOLEAN)), 3716 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)), 3717 .call = parse_qo_destroy, 3718 }, 3719 [QUEUE_DESTROY_ID] = { 3720 .name = "rule", 3721 .help = "specify rule id to destroy", 3722 .next = NEXT(next_queue_destroy_attr, 3723 NEXT_ENTRY(COMMON_UNSIGNED)), 3724 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, 3725 args.destroy.rule)), 3726 .call = parse_qo_destroy, 3727 }, 3728 [QUEUE_UPDATE_ID] = { 3729 .name = "rule", 3730 .help = "specify rule id to update", 3731 .next = NEXT(NEXT_ENTRY(QUEUE_ACTIONS_TEMPLATE), 3732 NEXT_ENTRY(COMMON_UNSIGNED)), 3733 .args = ARGS(ARGS_ENTRY(struct buffer, 3734 args.vc.rule_id)), 3735 .call = parse_qo, 3736 }, 3737 /* Queue indirect action arguments */ 3738 [QUEUE_INDIRECT_ACTION_CREATE] = { 3739 .name = "create", 3740 .help = "create indirect action", 3741 .next = NEXT(next_qia_create_attr), 3742 .call = parse_qia, 3743 }, 3744 [QUEUE_INDIRECT_ACTION_UPDATE] = { 3745 .name = "update", 3746 .help = "update indirect action", 3747 .next = NEXT(next_qia_update_attr, 3748 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), 3749 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)), 3750 .call = parse_qia, 3751 }, 3752 [QUEUE_INDIRECT_ACTION_DESTROY] = { 3753 .name = "destroy", 3754 .help = "destroy indirect action", 3755 .next = NEXT(next_qia_destroy_attr), 3756 .call = parse_qia_destroy, 3757 }, 3758 [QUEUE_INDIRECT_ACTION_QUERY] = { 3759 .name = "query", 3760 .help = "query indirect action", 3761 .next = NEXT(next_qia_query_attr, 3762 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), 3763 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)), 3764 .call = parse_qia, 3765 }, 3766 /* Indirect action destroy arguments. */ 3767 [QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = { 3768 .name = "postpone", 3769 .help = "postpone destroy operation", 3770 .next = NEXT(next_qia_destroy_attr, 3771 NEXT_ENTRY(COMMON_BOOLEAN)), 3772 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)), 3773 }, 3774 [QUEUE_INDIRECT_ACTION_DESTROY_ID] = { 3775 .name = "action_id", 3776 .help = "specify a indirect action id to destroy", 3777 .next = NEXT(next_qia_destroy_attr, 3778 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), 3779 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, 3780 args.ia_destroy.action_id)), 3781 .call = parse_qia_destroy, 3782 }, 3783 [QUEUE_INDIRECT_ACTION_QUERY_UPDATE] = { 3784 .name = "query_update", 3785 .help = "indirect query [and|or] update action", 3786 .next = NEXT(next_qia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), 3787 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)), 3788 .call = parse_qia 3789 }, 3790 [QUEUE_INDIRECT_ACTION_QU_MODE] = { 3791 .name = "mode", 3792 .help = "indirect query [and|or] update action", 3793 .next = NEXT(next_qia_qu_attr, 3794 NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)), 3795 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)), 3796 .call = parse_qia 3797 }, 3798 /* Indirect action update arguments. */ 3799 [QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE] = { 3800 .name = "postpone", 3801 .help = "postpone update operation", 3802 .next = NEXT(next_qia_update_attr, 3803 NEXT_ENTRY(COMMON_BOOLEAN)), 3804 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)), 3805 }, 3806 /* Indirect action update arguments. */ 3807 [QUEUE_INDIRECT_ACTION_QUERY_POSTPONE] = { 3808 .name = "postpone", 3809 .help = "postpone query operation", 3810 .next = NEXT(next_qia_query_attr, 3811 NEXT_ENTRY(COMMON_BOOLEAN)), 3812 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)), 3813 }, 3814 /* Indirect action create arguments. */ 3815 [QUEUE_INDIRECT_ACTION_CREATE_ID] = { 3816 .name = "action_id", 3817 .help = "specify a indirect action id to create", 3818 .next = NEXT(next_qia_create_attr, 3819 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), 3820 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)), 3821 }, 3822 [QUEUE_INDIRECT_ACTION_INGRESS] = { 3823 .name = "ingress", 3824 .help = "affect rule to ingress", 3825 .next = NEXT(next_qia_create_attr), 3826 .call = parse_qia, 3827 }, 3828 [QUEUE_INDIRECT_ACTION_EGRESS] = { 3829 .name = "egress", 3830 .help = "affect rule to egress", 3831 .next = NEXT(next_qia_create_attr), 3832 .call = parse_qia, 3833 }, 3834 [QUEUE_INDIRECT_ACTION_TRANSFER] = { 3835 .name = "transfer", 3836 .help = "affect rule to transfer", 3837 .next = NEXT(next_qia_create_attr), 3838 .call = parse_qia, 3839 }, 3840 [QUEUE_INDIRECT_ACTION_CREATE_POSTPONE] = { 3841 .name = "postpone", 3842 .help = "postpone create operation", 3843 .next = NEXT(next_qia_create_attr, 3844 NEXT_ENTRY(COMMON_BOOLEAN)), 3845 .args = ARGS(ARGS_ENTRY(struct buffer, postpone)), 3846 }, 3847 [QUEUE_INDIRECT_ACTION_SPEC] = { 3848 .name = "action", 3849 .help = "specify action to create indirect handle", 3850 .next = NEXT(next_action), 3851 }, 3852 [QUEUE_INDIRECT_ACTION_LIST] = { 3853 .name = "list", 3854 .help = "specify actions for indirect handle list", 3855 .next = NEXT(NEXT_ENTRY(ACTIONS, END)), 3856 .call = parse_qia, 3857 }, 3858 /* Top-level command. */ 3859 [PUSH] = { 3860 .name = "push", 3861 .help = "push enqueued operations", 3862 .next = NEXT(NEXT_ENTRY(PUSH_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)), 3863 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3864 .call = parse_push, 3865 }, 3866 /* Sub-level commands. */ 3867 [PUSH_QUEUE] = { 3868 .name = "queue", 3869 .help = "specify queue id", 3870 .next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)), 3871 .args = ARGS(ARGS_ENTRY(struct buffer, queue)), 3872 }, 3873 /* Top-level command. */ 3874 [PULL] = { 3875 .name = "pull", 3876 .help = "pull flow operations results", 3877 .next = NEXT(NEXT_ENTRY(PULL_QUEUE), NEXT_ENTRY(COMMON_PORT_ID)), 3878 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3879 .call = parse_pull, 3880 }, 3881 /* Sub-level commands. */ 3882 [PULL_QUEUE] = { 3883 .name = "queue", 3884 .help = "specify queue id", 3885 .next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(COMMON_QUEUE_ID)), 3886 .args = ARGS(ARGS_ENTRY(struct buffer, queue)), 3887 }, 3888 /* Top-level command. */ 3889 [HASH] = { 3890 .name = "hash", 3891 .help = "calculate hash for a given pattern in a given template table", 3892 .next = NEXT(next_hash_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), 3893 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3894 .call = parse_hash, 3895 }, 3896 /* Sub-level commands. */ 3897 [HASH_CALC_TABLE] = { 3898 .name = "template_table", 3899 .help = "specify table id", 3900 .next = NEXT(NEXT_ENTRY(HASH_CALC_PATTERN_INDEX), 3901 NEXT_ENTRY(COMMON_TABLE_ID)), 3902 .args = ARGS(ARGS_ENTRY(struct buffer, 3903 args.vc.table_id)), 3904 .call = parse_hash, 3905 }, 3906 [HASH_CALC_ENCAP] = { 3907 .name = "encap", 3908 .help = "calculates encap hash", 3909 .next = NEXT(next_hash_encap_dest_subcmd), 3910 .call = parse_hash, 3911 }, 3912 [HASH_CALC_PATTERN_INDEX] = { 3913 .name = "pattern_template", 3914 .help = "specify pattern template id", 3915 .next = NEXT(NEXT_ENTRY(ITEM_PATTERN), 3916 NEXT_ENTRY(COMMON_UNSIGNED)), 3917 .args = ARGS(ARGS_ENTRY(struct buffer, 3918 args.vc.pat_templ_id)), 3919 .call = parse_hash, 3920 }, 3921 [ENCAP_HASH_FIELD_SRC_PORT] = { 3922 .name = "hash_field_sport", 3923 .help = "the encap hash field is src port", 3924 .next = NEXT(NEXT_ENTRY(ITEM_PATTERN)), 3925 .call = parse_hash, 3926 }, 3927 [ENCAP_HASH_FIELD_GRE_FLOW_ID] = { 3928 .name = "hash_field_flow_id", 3929 .help = "the encap hash field is NVGRE flow id", 3930 .next = NEXT(NEXT_ENTRY(ITEM_PATTERN)), 3931 .call = parse_hash, 3932 }, 3933 /* Top-level command. */ 3934 [INDIRECT_ACTION] = { 3935 .name = "indirect_action", 3936 .type = "{command} {port_id} [{arg} [...]]", 3937 .help = "manage indirect actions", 3938 .next = NEXT(next_ia_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), 3939 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3940 .call = parse_ia, 3941 }, 3942 /* Sub-level commands. */ 3943 [INDIRECT_ACTION_CREATE] = { 3944 .name = "create", 3945 .help = "create indirect action", 3946 .next = NEXT(next_ia_create_attr), 3947 .call = parse_ia, 3948 }, 3949 [INDIRECT_ACTION_UPDATE] = { 3950 .name = "update", 3951 .help = "update indirect action", 3952 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_SPEC), 3953 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), 3954 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)), 3955 .call = parse_ia, 3956 }, 3957 [INDIRECT_ACTION_DESTROY] = { 3958 .name = "destroy", 3959 .help = "destroy indirect action", 3960 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_DESTROY_ID)), 3961 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3962 .call = parse_ia_destroy, 3963 }, 3964 [INDIRECT_ACTION_QUERY] = { 3965 .name = "query", 3966 .help = "query indirect action", 3967 .next = NEXT(NEXT_ENTRY(END), 3968 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), 3969 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)), 3970 .call = parse_ia, 3971 }, 3972 [INDIRECT_ACTION_QUERY_UPDATE] = { 3973 .name = "query_update", 3974 .help = "query [and|or] update", 3975 .next = NEXT(next_ia_qu_attr, NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), 3976 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.action_id)), 3977 .call = parse_ia 3978 }, 3979 [INDIRECT_ACTION_QU_MODE] = { 3980 .name = "mode", 3981 .help = "query_update mode", 3982 .next = NEXT(next_ia_qu_attr, 3983 NEXT_ENTRY(INDIRECT_ACTION_QU_MODE_NAME)), 3984 .args = ARGS(ARGS_ENTRY(struct buffer, args.ia.qu_mode)), 3985 .call = parse_ia, 3986 }, 3987 [INDIRECT_ACTION_QU_MODE_NAME] = { 3988 .name = "mode_name", 3989 .help = "query-update mode name", 3990 .call = parse_qu_mode_name, 3991 .comp = comp_qu_mode_name, 3992 }, 3993 [VALIDATE] = { 3994 .name = "validate", 3995 .help = "check whether a flow rule can be created", 3996 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)), 3997 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 3998 .call = parse_vc, 3999 }, 4000 [CREATE] = { 4001 .name = "create", 4002 .help = "create a flow rule", 4003 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PORT_ID)), 4004 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 4005 .call = parse_vc, 4006 }, 4007 [DESTROY] = { 4008 .name = "destroy", 4009 .help = "destroy specific flow rules", 4010 .next = NEXT(next_destroy_attr, 4011 NEXT_ENTRY(COMMON_PORT_ID)), 4012 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 4013 .call = parse_destroy, 4014 }, 4015 [FLUSH] = { 4016 .name = "flush", 4017 .help = "destroy all flow rules", 4018 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)), 4019 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 4020 .call = parse_flush, 4021 }, 4022 [DUMP] = { 4023 .name = "dump", 4024 .help = "dump single/all flow rules to file", 4025 .next = NEXT(next_dump_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), 4026 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 4027 .call = parse_dump, 4028 }, 4029 [QUERY] = { 4030 .name = "query", 4031 .help = "query an existing flow rule", 4032 .next = NEXT(next_query_attr, NEXT_ENTRY(QUERY_ACTION), 4033 NEXT_ENTRY(COMMON_RULE_ID), 4034 NEXT_ENTRY(COMMON_PORT_ID)), 4035 .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type), 4036 ARGS_ENTRY(struct buffer, args.query.rule), 4037 ARGS_ENTRY(struct buffer, port)), 4038 .call = parse_query, 4039 }, 4040 [LIST] = { 4041 .name = "list", 4042 .help = "list existing flow rules", 4043 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_PORT_ID)), 4044 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 4045 .call = parse_list, 4046 }, 4047 [AGED] = { 4048 .name = "aged", 4049 .help = "list and destroy aged flows", 4050 .next = NEXT(next_aged_attr, NEXT_ENTRY(COMMON_PORT_ID)), 4051 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 4052 .call = parse_aged, 4053 }, 4054 [ISOLATE] = { 4055 .name = "isolate", 4056 .help = "restrict ingress traffic to the defined flow rules", 4057 .next = NEXT(NEXT_ENTRY(COMMON_BOOLEAN), 4058 NEXT_ENTRY(COMMON_PORT_ID)), 4059 .args = ARGS(ARGS_ENTRY(struct buffer, args.isolate.set), 4060 ARGS_ENTRY(struct buffer, port)), 4061 .call = parse_isolate, 4062 }, 4063 [FLEX] = { 4064 .name = "flex_item", 4065 .help = "flex item API", 4066 .next = NEXT(next_flex_item), 4067 .call = parse_flex, 4068 }, 4069 [FLEX_ITEM_INIT] = { 4070 .name = "init", 4071 .help = "flex item init", 4072 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token), 4073 ARGS_ENTRY(struct buffer, port)), 4074 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN), 4075 NEXT_ENTRY(COMMON_PORT_ID)), 4076 .call = parse_flex 4077 }, 4078 [FLEX_ITEM_CREATE] = { 4079 .name = "create", 4080 .help = "flex item create", 4081 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.filename), 4082 ARGS_ENTRY(struct buffer, args.flex.token), 4083 ARGS_ENTRY(struct buffer, port)), 4084 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH), 4085 NEXT_ENTRY(COMMON_FLEX_TOKEN), 4086 NEXT_ENTRY(COMMON_PORT_ID)), 4087 .call = parse_flex 4088 }, 4089 [FLEX_ITEM_DESTROY] = { 4090 .name = "destroy", 4091 .help = "flex item destroy", 4092 .args = ARGS(ARGS_ENTRY(struct buffer, args.flex.token), 4093 ARGS_ENTRY(struct buffer, port)), 4094 .next = NEXT(NEXT_ENTRY(COMMON_FLEX_TOKEN), 4095 NEXT_ENTRY(COMMON_PORT_ID)), 4096 .call = parse_flex 4097 }, 4098 [TUNNEL] = { 4099 .name = "tunnel", 4100 .help = "new tunnel API", 4101 .next = NEXT(NEXT_ENTRY 4102 (TUNNEL_CREATE, TUNNEL_LIST, TUNNEL_DESTROY)), 4103 .call = parse_tunnel, 4104 }, 4105 /* Tunnel arguments. */ 4106 [TUNNEL_CREATE] = { 4107 .name = "create", 4108 .help = "create new tunnel object", 4109 .next = NEXT(NEXT_ENTRY(TUNNEL_CREATE_TYPE), 4110 NEXT_ENTRY(COMMON_PORT_ID)), 4111 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 4112 .call = parse_tunnel, 4113 }, 4114 [TUNNEL_CREATE_TYPE] = { 4115 .name = "type", 4116 .help = "create new tunnel", 4117 .next = NEXT(NEXT_ENTRY(COMMON_FILE_PATH)), 4118 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, type)), 4119 .call = parse_tunnel, 4120 }, 4121 [TUNNEL_DESTROY] = { 4122 .name = "destroy", 4123 .help = "destroy tunnel", 4124 .next = NEXT(NEXT_ENTRY(TUNNEL_DESTROY_ID), 4125 NEXT_ENTRY(COMMON_PORT_ID)), 4126 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 4127 .call = parse_tunnel, 4128 }, 4129 [TUNNEL_DESTROY_ID] = { 4130 .name = "id", 4131 .help = "tunnel identifier to destroy", 4132 .next = NEXT(NEXT_ENTRY(COMMON_UNSIGNED)), 4133 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)), 4134 .call = parse_tunnel, 4135 }, 4136 [TUNNEL_LIST] = { 4137 .name = "list", 4138 .help = "list existing tunnels", 4139 .next = NEXT(NEXT_ENTRY(COMMON_PORT_ID)), 4140 .args = ARGS(ARGS_ENTRY(struct buffer, port)), 4141 .call = parse_tunnel, 4142 }, 4143 /* Destroy arguments. */ 4144 [DESTROY_RULE] = { 4145 .name = "rule", 4146 .help = "specify a rule identifier", 4147 .next = NEXT(next_destroy_attr, NEXT_ENTRY(COMMON_RULE_ID)), 4148 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)), 4149 .call = parse_destroy, 4150 }, 4151 [DESTROY_IS_USER_ID] = { 4152 .name = "user_id", 4153 .help = "rule identifier is user-id", 4154 .next = NEXT(next_destroy_attr), 4155 .call = parse_destroy, 4156 }, 4157 /* Dump arguments. */ 4158 [DUMP_ALL] = { 4159 .name = "all", 4160 .help = "dump all", 4161 .next = NEXT(next_dump_attr), 4162 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file)), 4163 .call = parse_dump, 4164 }, 4165 [DUMP_ONE] = { 4166 .name = "rule", 4167 .help = "dump one rule", 4168 .next = NEXT(next_dump_attr, NEXT_ENTRY(COMMON_RULE_ID)), 4169 .args = ARGS(ARGS_ENTRY(struct buffer, args.dump.file), 4170 ARGS_ENTRY(struct buffer, args.dump.rule)), 4171 .call = parse_dump, 4172 }, 4173 [DUMP_IS_USER_ID] = { 4174 .name = "user_id", 4175 .help = "rule identifier is user-id", 4176 .next = NEXT(next_dump_subcmd), 4177 .call = parse_dump, 4178 }, 4179 /* Query arguments. */ 4180 [QUERY_ACTION] = { 4181 .name = "{action}", 4182 .type = "ACTION", 4183 .help = "action to query, must be part of the rule", 4184 .call = parse_action, 4185 .comp = comp_action, 4186 }, 4187 [QUERY_IS_USER_ID] = { 4188 .name = "user_id", 4189 .help = "rule identifier is user-id", 4190 .next = NEXT(next_query_attr), 4191 .call = parse_query, 4192 }, 4193 /* List arguments. */ 4194 [LIST_GROUP] = { 4195 .name = "group", 4196 .help = "specify a group", 4197 .next = NEXT(next_list_attr, NEXT_ENTRY(COMMON_GROUP_ID)), 4198 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)), 4199 .call = parse_list, 4200 }, 4201 [AGED_DESTROY] = { 4202 .name = "destroy", 4203 .help = "specify aged flows need be destroyed", 4204 .call = parse_aged, 4205 .comp = comp_none, 4206 }, 4207 /* Validate/create attributes. */ 4208 [VC_GROUP] = { 4209 .name = "group", 4210 .help = "specify a group", 4211 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_GROUP_ID)), 4212 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, group)), 4213 .call = parse_vc, 4214 }, 4215 [VC_PRIORITY] = { 4216 .name = "priority", 4217 .help = "specify a priority level", 4218 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_PRIORITY_LEVEL)), 4219 .args = ARGS(ARGS_ENTRY(struct rte_flow_attr, priority)), 4220 .call = parse_vc, 4221 }, 4222 [VC_INGRESS] = { 4223 .name = "ingress", 4224 .help = "affect rule to ingress", 4225 .next = NEXT(next_vc_attr), 4226 .call = parse_vc, 4227 }, 4228 [VC_EGRESS] = { 4229 .name = "egress", 4230 .help = "affect rule to egress", 4231 .next = NEXT(next_vc_attr), 4232 .call = parse_vc, 4233 }, 4234 [VC_TRANSFER] = { 4235 .name = "transfer", 4236 .help = "apply rule directly to endpoints found in pattern", 4237 .next = NEXT(next_vc_attr), 4238 .call = parse_vc, 4239 }, 4240 [VC_TUNNEL_SET] = { 4241 .name = "tunnel_set", 4242 .help = "tunnel steer rule", 4243 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)), 4244 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)), 4245 .call = parse_vc, 4246 }, 4247 [VC_TUNNEL_MATCH] = { 4248 .name = "tunnel_match", 4249 .help = "tunnel match rule", 4250 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)), 4251 .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)), 4252 .call = parse_vc, 4253 }, 4254 [VC_USER_ID] = { 4255 .name = "user_id", 4256 .help = "specify a user id to create", 4257 .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)), 4258 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.user_id)), 4259 .call = parse_vc, 4260 }, 4261 /* Validate/create pattern. */ 4262 [ITEM_PATTERN] = { 4263 .name = "pattern", 4264 .help = "submit a list of pattern items", 4265 .next = NEXT(next_item), 4266 .call = parse_vc, 4267 }, 4268 [ITEM_PARAM_IS] = { 4269 .name = "is", 4270 .help = "match value perfectly (with full bit-mask)", 4271 .call = parse_vc_spec, 4272 }, 4273 [ITEM_PARAM_SPEC] = { 4274 .name = "spec", 4275 .help = "match value according to configured bit-mask", 4276 .call = parse_vc_spec, 4277 }, 4278 [ITEM_PARAM_LAST] = { 4279 .name = "last", 4280 .help = "specify upper bound to establish a range", 4281 .call = parse_vc_spec, 4282 }, 4283 [ITEM_PARAM_MASK] = { 4284 .name = "mask", 4285 .help = "specify bit-mask with relevant bits set to one", 4286 .call = parse_vc_spec, 4287 }, 4288 [ITEM_PARAM_PREFIX] = { 4289 .name = "prefix", 4290 .help = "generate bit-mask from a prefix length", 4291 .call = parse_vc_spec, 4292 }, 4293 [ITEM_NEXT] = { 4294 .name = "/", 4295 .help = "specify next pattern item", 4296 .next = NEXT(next_item), 4297 }, 4298 [ITEM_END] = { 4299 .name = "end", 4300 .help = "end list of pattern items", 4301 .priv = PRIV_ITEM(END, 0), 4302 .next = NEXT(NEXT_ENTRY(ACTIONS, END)), 4303 .call = parse_vc, 4304 }, 4305 [ITEM_VOID] = { 4306 .name = "void", 4307 .help = "no-op pattern item", 4308 .priv = PRIV_ITEM(VOID, 0), 4309 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)), 4310 .call = parse_vc, 4311 }, 4312 [ITEM_INVERT] = { 4313 .name = "invert", 4314 .help = "perform actions when pattern does not match", 4315 .priv = PRIV_ITEM(INVERT, 0), 4316 .next = NEXT(NEXT_ENTRY(ITEM_NEXT)), 4317 .call = parse_vc, 4318 }, 4319 [ITEM_ANY] = { 4320 .name = "any", 4321 .help = "match any protocol for the current layer", 4322 .priv = PRIV_ITEM(ANY, sizeof(struct rte_flow_item_any)), 4323 .next = NEXT(item_any), 4324 .call = parse_vc, 4325 }, 4326 [ITEM_ANY_NUM] = { 4327 .name = "num", 4328 .help = "number of layers covered", 4329 .next = NEXT(item_any, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 4330 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_any, num)), 4331 }, 4332 [ITEM_PORT_ID] = { 4333 .name = "port_id", 4334 .help = "match traffic from/to a given DPDK port ID", 4335 .priv = PRIV_ITEM(PORT_ID, 4336 sizeof(struct rte_flow_item_port_id)), 4337 .next = NEXT(item_port_id), 4338 .call = parse_vc, 4339 }, 4340 [ITEM_PORT_ID_ID] = { 4341 .name = "id", 4342 .help = "DPDK port ID", 4343 .next = NEXT(item_port_id, NEXT_ENTRY(COMMON_UNSIGNED), 4344 item_param), 4345 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_port_id, id)), 4346 }, 4347 [ITEM_MARK] = { 4348 .name = "mark", 4349 .help = "match traffic against value set in previously matched rule", 4350 .priv = PRIV_ITEM(MARK, sizeof(struct rte_flow_item_mark)), 4351 .next = NEXT(item_mark), 4352 .call = parse_vc, 4353 }, 4354 [ITEM_MARK_ID] = { 4355 .name = "id", 4356 .help = "Integer value to match against", 4357 .next = NEXT(item_mark, NEXT_ENTRY(COMMON_UNSIGNED), 4358 item_param), 4359 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_mark, id)), 4360 }, 4361 [ITEM_RAW] = { 4362 .name = "raw", 4363 .help = "match an arbitrary byte string", 4364 .priv = PRIV_ITEM(RAW, ITEM_RAW_SIZE), 4365 .next = NEXT(item_raw), 4366 .call = parse_vc, 4367 }, 4368 [ITEM_RAW_RELATIVE] = { 4369 .name = "relative", 4370 .help = "look for pattern after the previous item", 4371 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param), 4372 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw, 4373 relative, 1)), 4374 }, 4375 [ITEM_RAW_SEARCH] = { 4376 .name = "search", 4377 .help = "search pattern from offset (see also limit)", 4378 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_BOOLEAN), item_param), 4379 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_raw, 4380 search, 1)), 4381 }, 4382 [ITEM_RAW_OFFSET] = { 4383 .name = "offset", 4384 .help = "absolute or relative offset for pattern", 4385 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_INTEGER), item_param), 4386 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, offset)), 4387 }, 4388 [ITEM_RAW_LIMIT] = { 4389 .name = "limit", 4390 .help = "search area limit for start of pattern", 4391 .next = NEXT(item_raw, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 4392 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, limit)), 4393 }, 4394 [ITEM_RAW_PATTERN] = { 4395 .name = "pattern", 4396 .help = "byte string to look for", 4397 .next = NEXT(item_raw, 4398 NEXT_ENTRY(COMMON_STRING), 4399 NEXT_ENTRY(ITEM_PARAM_IS, 4400 ITEM_PARAM_SPEC, 4401 ITEM_PARAM_MASK)), 4402 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern), 4403 ARGS_ENTRY(struct rte_flow_item_raw, length), 4404 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw), 4405 ITEM_RAW_PATTERN_SIZE)), 4406 }, 4407 [ITEM_RAW_PATTERN_HEX] = { 4408 .name = "pattern_hex", 4409 .help = "hex string to look for", 4410 .next = NEXT(item_raw, 4411 NEXT_ENTRY(COMMON_HEX), 4412 NEXT_ENTRY(ITEM_PARAM_IS, 4413 ITEM_PARAM_SPEC, 4414 ITEM_PARAM_MASK)), 4415 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_raw, pattern), 4416 ARGS_ENTRY(struct rte_flow_item_raw, length), 4417 ARGS_ENTRY_ARB(sizeof(struct rte_flow_item_raw), 4418 ITEM_RAW_PATTERN_SIZE)), 4419 }, 4420 [ITEM_ETH] = { 4421 .name = "eth", 4422 .help = "match Ethernet header", 4423 .priv = PRIV_ITEM(ETH, sizeof(struct rte_flow_item_eth)), 4424 .next = NEXT(item_eth), 4425 .call = parse_vc, 4426 }, 4427 [ITEM_ETH_DST] = { 4428 .name = "dst", 4429 .help = "destination MAC", 4430 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param), 4431 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.dst_addr)), 4432 }, 4433 [ITEM_ETH_SRC] = { 4434 .name = "src", 4435 .help = "source MAC", 4436 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_MAC_ADDR), item_param), 4437 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.src_addr)), 4438 }, 4439 [ITEM_ETH_TYPE] = { 4440 .name = "type", 4441 .help = "EtherType", 4442 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 4443 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_eth, hdr.ether_type)), 4444 }, 4445 [ITEM_ETH_HAS_VLAN] = { 4446 .name = "has_vlan", 4447 .help = "packet header contains VLAN", 4448 .next = NEXT(item_eth, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 4449 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_eth, 4450 has_vlan, 1)), 4451 }, 4452 [ITEM_VLAN] = { 4453 .name = "vlan", 4454 .help = "match 802.1Q/ad VLAN tag", 4455 .priv = PRIV_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)), 4456 .next = NEXT(item_vlan), 4457 .call = parse_vc, 4458 }, 4459 [ITEM_VLAN_TCI] = { 4460 .name = "tci", 4461 .help = "tag control information", 4462 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED), 4463 item_param), 4464 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, hdr.vlan_tci)), 4465 }, 4466 [ITEM_VLAN_PCP] = { 4467 .name = "pcp", 4468 .help = "priority code point", 4469 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED), 4470 item_param), 4471 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan, 4472 hdr.vlan_tci, "\xe0\x00")), 4473 }, 4474 [ITEM_VLAN_DEI] = { 4475 .name = "dei", 4476 .help = "drop eligible indicator", 4477 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED), 4478 item_param), 4479 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan, 4480 hdr.vlan_tci, "\x10\x00")), 4481 }, 4482 [ITEM_VLAN_VID] = { 4483 .name = "vid", 4484 .help = "VLAN identifier", 4485 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED), 4486 item_param), 4487 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_vlan, 4488 hdr.vlan_tci, "\x0f\xff")), 4489 }, 4490 [ITEM_VLAN_INNER_TYPE] = { 4491 .name = "inner_type", 4492 .help = "inner EtherType", 4493 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED), 4494 item_param), 4495 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vlan, 4496 hdr.eth_proto)), 4497 }, 4498 [ITEM_VLAN_HAS_MORE_VLAN] = { 4499 .name = "has_more_vlan", 4500 .help = "packet header contains another VLAN", 4501 .next = NEXT(item_vlan, NEXT_ENTRY(COMMON_UNSIGNED), 4502 item_param), 4503 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_vlan, 4504 has_more_vlan, 1)), 4505 }, 4506 [ITEM_IPV4] = { 4507 .name = "ipv4", 4508 .help = "match IPv4 header", 4509 .priv = PRIV_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)), 4510 .next = NEXT(item_ipv4), 4511 .call = parse_vc, 4512 }, 4513 [ITEM_IPV4_VER_IHL] = { 4514 .name = "version_ihl", 4515 .help = "match header length", 4516 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED), 4517 item_param), 4518 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv4, 4519 hdr.version_ihl)), 4520 }, 4521 [ITEM_IPV4_TOS] = { 4522 .name = "tos", 4523 .help = "type of service", 4524 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED), 4525 item_param), 4526 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 4527 hdr.type_of_service)), 4528 }, 4529 [ITEM_IPV4_LENGTH] = { 4530 .name = "length", 4531 .help = "total length", 4532 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED), 4533 item_param), 4534 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 4535 hdr.total_length)), 4536 }, 4537 [ITEM_IPV4_ID] = { 4538 .name = "packet_id", 4539 .help = "fragment packet id", 4540 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED), 4541 item_param), 4542 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 4543 hdr.packet_id)), 4544 }, 4545 [ITEM_IPV4_FRAGMENT_OFFSET] = { 4546 .name = "fragment_offset", 4547 .help = "fragmentation flags and fragment offset", 4548 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED), 4549 item_param), 4550 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 4551 hdr.fragment_offset)), 4552 }, 4553 [ITEM_IPV4_TTL] = { 4554 .name = "ttl", 4555 .help = "time to live", 4556 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED), 4557 item_param), 4558 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 4559 hdr.time_to_live)), 4560 }, 4561 [ITEM_IPV4_PROTO] = { 4562 .name = "proto", 4563 .help = "next protocol ID", 4564 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_UNSIGNED), 4565 item_param), 4566 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 4567 hdr.next_proto_id)), 4568 }, 4569 [ITEM_IPV4_SRC] = { 4570 .name = "src", 4571 .help = "source address", 4572 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR), 4573 item_param), 4574 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 4575 hdr.src_addr)), 4576 }, 4577 [ITEM_IPV4_DST] = { 4578 .name = "dst", 4579 .help = "destination address", 4580 .next = NEXT(item_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR), 4581 item_param), 4582 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv4, 4583 hdr.dst_addr)), 4584 }, 4585 [ITEM_IPV6] = { 4586 .name = "ipv6", 4587 .help = "match IPv6 header", 4588 .priv = PRIV_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)), 4589 .next = NEXT(item_ipv6), 4590 .call = parse_vc, 4591 }, 4592 [ITEM_IPV6_TC] = { 4593 .name = "tc", 4594 .help = "traffic class", 4595 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED), 4596 item_param), 4597 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6, 4598 hdr.vtc_flow, 4599 "\x0f\xf0\x00\x00")), 4600 }, 4601 [ITEM_IPV6_FLOW] = { 4602 .name = "flow", 4603 .help = "flow label", 4604 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED), 4605 item_param), 4606 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_ipv6, 4607 hdr.vtc_flow, 4608 "\x00\x0f\xff\xff")), 4609 }, 4610 [ITEM_IPV6_LEN] = { 4611 .name = "length", 4612 .help = "payload length", 4613 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED), 4614 item_param), 4615 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 4616 hdr.payload_len)), 4617 }, 4618 [ITEM_IPV6_PROTO] = { 4619 .name = "proto", 4620 .help = "protocol (next header)", 4621 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED), 4622 item_param), 4623 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 4624 hdr.proto)), 4625 }, 4626 [ITEM_IPV6_HOP] = { 4627 .name = "hop", 4628 .help = "hop limit", 4629 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED), 4630 item_param), 4631 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 4632 hdr.hop_limits)), 4633 }, 4634 [ITEM_IPV6_SRC] = { 4635 .name = "src", 4636 .help = "source address", 4637 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR), 4638 item_param), 4639 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 4640 hdr.src_addr)), 4641 }, 4642 [ITEM_IPV6_DST] = { 4643 .name = "dst", 4644 .help = "destination address", 4645 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_IPV6_ADDR), 4646 item_param), 4647 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6, 4648 hdr.dst_addr)), 4649 }, 4650 [ITEM_IPV6_HAS_FRAG_EXT] = { 4651 .name = "has_frag_ext", 4652 .help = "fragment packet attribute", 4653 .next = NEXT(item_ipv6, NEXT_ENTRY(COMMON_UNSIGNED), 4654 item_param), 4655 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_ipv6, 4656 has_frag_ext, 1)), 4657 }, 4658 [ITEM_IPV6_ROUTING_EXT] = { 4659 .name = "ipv6_routing_ext", 4660 .help = "match IPv6 routing extension header", 4661 .priv = PRIV_ITEM(IPV6_ROUTING_EXT, 4662 sizeof(struct rte_flow_item_ipv6_routing_ext)), 4663 .next = NEXT(item_ipv6_routing_ext), 4664 .call = parse_vc, 4665 }, 4666 [ITEM_IPV6_ROUTING_EXT_TYPE] = { 4667 .name = "ext_type", 4668 .help = "match IPv6 routing extension header type", 4669 .next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED), 4670 item_param), 4671 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext, 4672 hdr.type)), 4673 }, 4674 [ITEM_IPV6_ROUTING_EXT_NEXT_HDR] = { 4675 .name = "ext_next_hdr", 4676 .help = "match IPv6 routing extension header next header type", 4677 .next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED), 4678 item_param), 4679 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext, 4680 hdr.next_hdr)), 4681 }, 4682 [ITEM_IPV6_ROUTING_EXT_SEG_LEFT] = { 4683 .name = "ext_seg_left", 4684 .help = "match IPv6 routing extension header segment left", 4685 .next = NEXT(item_ipv6_routing_ext, NEXT_ENTRY(COMMON_UNSIGNED), 4686 item_param), 4687 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_routing_ext, 4688 hdr.segments_left)), 4689 }, 4690 [ITEM_ICMP] = { 4691 .name = "icmp", 4692 .help = "match ICMP header", 4693 .priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)), 4694 .next = NEXT(item_icmp), 4695 .call = parse_vc, 4696 }, 4697 [ITEM_ICMP_TYPE] = { 4698 .name = "type", 4699 .help = "ICMP packet type", 4700 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED), 4701 item_param), 4702 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp, 4703 hdr.icmp_type)), 4704 }, 4705 [ITEM_ICMP_CODE] = { 4706 .name = "code", 4707 .help = "ICMP packet code", 4708 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED), 4709 item_param), 4710 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp, 4711 hdr.icmp_code)), 4712 }, 4713 [ITEM_ICMP_IDENT] = { 4714 .name = "ident", 4715 .help = "ICMP packet identifier", 4716 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED), 4717 item_param), 4718 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp, 4719 hdr.icmp_ident)), 4720 }, 4721 [ITEM_ICMP_SEQ] = { 4722 .name = "seq", 4723 .help = "ICMP packet sequence number", 4724 .next = NEXT(item_icmp, NEXT_ENTRY(COMMON_UNSIGNED), 4725 item_param), 4726 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp, 4727 hdr.icmp_seq_nb)), 4728 }, 4729 [ITEM_UDP] = { 4730 .name = "udp", 4731 .help = "match UDP header", 4732 .priv = PRIV_ITEM(UDP, sizeof(struct rte_flow_item_udp)), 4733 .next = NEXT(item_udp), 4734 .call = parse_vc, 4735 }, 4736 [ITEM_UDP_SRC] = { 4737 .name = "src", 4738 .help = "UDP source port", 4739 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), 4740 item_param), 4741 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp, 4742 hdr.src_port)), 4743 }, 4744 [ITEM_UDP_DST] = { 4745 .name = "dst", 4746 .help = "UDP destination port", 4747 .next = NEXT(item_udp, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 4748 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_udp, 4749 hdr.dst_port)), 4750 }, 4751 [ITEM_TCP] = { 4752 .name = "tcp", 4753 .help = "match TCP header", 4754 .priv = PRIV_ITEM(TCP, sizeof(struct rte_flow_item_tcp)), 4755 .next = NEXT(item_tcp), 4756 .call = parse_vc, 4757 }, 4758 [ITEM_TCP_SRC] = { 4759 .name = "src", 4760 .help = "TCP source port", 4761 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 4762 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp, 4763 hdr.src_port)), 4764 }, 4765 [ITEM_TCP_DST] = { 4766 .name = "dst", 4767 .help = "TCP destination port", 4768 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 4769 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp, 4770 hdr.dst_port)), 4771 }, 4772 [ITEM_TCP_FLAGS] = { 4773 .name = "flags", 4774 .help = "TCP flags", 4775 .next = NEXT(item_tcp, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 4776 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_tcp, 4777 hdr.tcp_flags)), 4778 }, 4779 [ITEM_SCTP] = { 4780 .name = "sctp", 4781 .help = "match SCTP header", 4782 .priv = PRIV_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)), 4783 .next = NEXT(item_sctp), 4784 .call = parse_vc, 4785 }, 4786 [ITEM_SCTP_SRC] = { 4787 .name = "src", 4788 .help = "SCTP source port", 4789 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED), 4790 item_param), 4791 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp, 4792 hdr.src_port)), 4793 }, 4794 [ITEM_SCTP_DST] = { 4795 .name = "dst", 4796 .help = "SCTP destination port", 4797 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED), 4798 item_param), 4799 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp, 4800 hdr.dst_port)), 4801 }, 4802 [ITEM_SCTP_TAG] = { 4803 .name = "tag", 4804 .help = "validation tag", 4805 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED), 4806 item_param), 4807 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp, 4808 hdr.tag)), 4809 }, 4810 [ITEM_SCTP_CKSUM] = { 4811 .name = "cksum", 4812 .help = "checksum", 4813 .next = NEXT(item_sctp, NEXT_ENTRY(COMMON_UNSIGNED), 4814 item_param), 4815 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_sctp, 4816 hdr.cksum)), 4817 }, 4818 [ITEM_VXLAN] = { 4819 .name = "vxlan", 4820 .help = "match VXLAN header", 4821 .priv = PRIV_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)), 4822 .next = NEXT(item_vxlan), 4823 .call = parse_vc, 4824 }, 4825 [ITEM_VXLAN_VNI] = { 4826 .name = "vni", 4827 .help = "VXLAN identifier", 4828 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED), 4829 item_param), 4830 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, hdr.vni)), 4831 }, 4832 [ITEM_VXLAN_LAST_RSVD] = { 4833 .name = "last_rsvd", 4834 .help = "VXLAN last reserved bits", 4835 .next = NEXT(item_vxlan, NEXT_ENTRY(COMMON_UNSIGNED), 4836 item_param), 4837 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan, 4838 hdr.rsvd1)), 4839 }, 4840 [ITEM_E_TAG] = { 4841 .name = "e_tag", 4842 .help = "match E-Tag header", 4843 .priv = PRIV_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)), 4844 .next = NEXT(item_e_tag), 4845 .call = parse_vc, 4846 }, 4847 [ITEM_E_TAG_GRP_ECID_B] = { 4848 .name = "grp_ecid_b", 4849 .help = "GRP and E-CID base", 4850 .next = NEXT(item_e_tag, NEXT_ENTRY(COMMON_UNSIGNED), 4851 item_param), 4852 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_e_tag, 4853 rsvd_grp_ecid_b, 4854 "\x3f\xff")), 4855 }, 4856 [ITEM_NVGRE] = { 4857 .name = "nvgre", 4858 .help = "match NVGRE header", 4859 .priv = PRIV_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)), 4860 .next = NEXT(item_nvgre), 4861 .call = parse_vc, 4862 }, 4863 [ITEM_NVGRE_TNI] = { 4864 .name = "tni", 4865 .help = "virtual subnet ID", 4866 .next = NEXT(item_nvgre, NEXT_ENTRY(COMMON_UNSIGNED), 4867 item_param), 4868 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_nvgre, tni)), 4869 }, 4870 [ITEM_MPLS] = { 4871 .name = "mpls", 4872 .help = "match MPLS header", 4873 .priv = PRIV_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)), 4874 .next = NEXT(item_mpls), 4875 .call = parse_vc, 4876 }, 4877 [ITEM_MPLS_LABEL] = { 4878 .name = "label", 4879 .help = "MPLS label", 4880 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED), 4881 item_param), 4882 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls, 4883 label_tc_s, 4884 "\xff\xff\xf0")), 4885 }, 4886 [ITEM_MPLS_TC] = { 4887 .name = "tc", 4888 .help = "MPLS Traffic Class", 4889 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED), 4890 item_param), 4891 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls, 4892 label_tc_s, 4893 "\x00\x00\x0e")), 4894 }, 4895 [ITEM_MPLS_S] = { 4896 .name = "s", 4897 .help = "MPLS Bottom-of-Stack", 4898 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED), 4899 item_param), 4900 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_mpls, 4901 label_tc_s, 4902 "\x00\x00\x01")), 4903 }, 4904 [ITEM_MPLS_TTL] = { 4905 .name = "ttl", 4906 .help = "MPLS Time-to-Live", 4907 .next = NEXT(item_mpls, NEXT_ENTRY(COMMON_UNSIGNED), 4908 item_param), 4909 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_mpls, ttl)), 4910 }, 4911 [ITEM_GRE] = { 4912 .name = "gre", 4913 .help = "match GRE header", 4914 .priv = PRIV_ITEM(GRE, sizeof(struct rte_flow_item_gre)), 4915 .next = NEXT(item_gre), 4916 .call = parse_vc, 4917 }, 4918 [ITEM_GRE_PROTO] = { 4919 .name = "protocol", 4920 .help = "GRE protocol type", 4921 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED), 4922 item_param), 4923 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre, 4924 protocol)), 4925 }, 4926 [ITEM_GRE_C_RSVD0_VER] = { 4927 .name = "c_rsvd0_ver", 4928 .help = 4929 "checksum (1b), undefined (1b), key bit (1b)," 4930 " sequence number (1b), reserved 0 (9b)," 4931 " version (3b)", 4932 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_UNSIGNED), 4933 item_param), 4934 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre, 4935 c_rsvd0_ver)), 4936 }, 4937 [ITEM_GRE_C_BIT] = { 4938 .name = "c_bit", 4939 .help = "checksum bit (C)", 4940 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), 4941 item_param), 4942 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre, 4943 c_rsvd0_ver, 4944 "\x80\x00\x00\x00")), 4945 }, 4946 [ITEM_GRE_S_BIT] = { 4947 .name = "s_bit", 4948 .help = "sequence number bit (S)", 4949 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param), 4950 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre, 4951 c_rsvd0_ver, 4952 "\x10\x00\x00\x00")), 4953 }, 4954 [ITEM_GRE_K_BIT] = { 4955 .name = "k_bit", 4956 .help = "key bit (K)", 4957 .next = NEXT(item_gre, NEXT_ENTRY(COMMON_BOOLEAN), item_param), 4958 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_gre, 4959 c_rsvd0_ver, 4960 "\x20\x00\x00\x00")), 4961 }, 4962 [ITEM_FUZZY] = { 4963 .name = "fuzzy", 4964 .help = "fuzzy pattern match, expect faster than default", 4965 .priv = PRIV_ITEM(FUZZY, 4966 sizeof(struct rte_flow_item_fuzzy)), 4967 .next = NEXT(item_fuzzy), 4968 .call = parse_vc, 4969 }, 4970 [ITEM_FUZZY_THRESH] = { 4971 .name = "thresh", 4972 .help = "match accuracy threshold", 4973 .next = NEXT(item_fuzzy, NEXT_ENTRY(COMMON_UNSIGNED), 4974 item_param), 4975 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_fuzzy, 4976 thresh)), 4977 }, 4978 [ITEM_GTP] = { 4979 .name = "gtp", 4980 .help = "match GTP header", 4981 .priv = PRIV_ITEM(GTP, sizeof(struct rte_flow_item_gtp)), 4982 .next = NEXT(item_gtp), 4983 .call = parse_vc, 4984 }, 4985 [ITEM_GTP_FLAGS] = { 4986 .name = "v_pt_rsv_flags", 4987 .help = "GTP flags", 4988 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 4989 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, 4990 hdr.gtp_hdr_info)), 4991 }, 4992 [ITEM_GTP_MSG_TYPE] = { 4993 .name = "msg_type", 4994 .help = "GTP message type", 4995 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 4996 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, hdr.msg_type)), 4997 }, 4998 [ITEM_GTP_TEID] = { 4999 .name = "teid", 5000 .help = "tunnel endpoint identifier", 5001 .next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 5002 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, hdr.teid)), 5003 }, 5004 [ITEM_GTPC] = { 5005 .name = "gtpc", 5006 .help = "match GTP header", 5007 .priv = PRIV_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)), 5008 .next = NEXT(item_gtp), 5009 .call = parse_vc, 5010 }, 5011 [ITEM_GTPU] = { 5012 .name = "gtpu", 5013 .help = "match GTP header", 5014 .priv = PRIV_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)), 5015 .next = NEXT(item_gtp), 5016 .call = parse_vc, 5017 }, 5018 [ITEM_GENEVE] = { 5019 .name = "geneve", 5020 .help = "match GENEVE header", 5021 .priv = PRIV_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)), 5022 .next = NEXT(item_geneve), 5023 .call = parse_vc, 5024 }, 5025 [ITEM_GENEVE_VNI] = { 5026 .name = "vni", 5027 .help = "virtual network identifier", 5028 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED), 5029 item_param), 5030 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, vni)), 5031 }, 5032 [ITEM_GENEVE_PROTO] = { 5033 .name = "protocol", 5034 .help = "GENEVE protocol type", 5035 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED), 5036 item_param), 5037 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve, 5038 protocol)), 5039 }, 5040 [ITEM_GENEVE_OPTLEN] = { 5041 .name = "optlen", 5042 .help = "GENEVE options length in dwords", 5043 .next = NEXT(item_geneve, NEXT_ENTRY(COMMON_UNSIGNED), 5044 item_param), 5045 .args = ARGS(ARGS_ENTRY_MASK_HTON(struct rte_flow_item_geneve, 5046 ver_opt_len_o_c_rsvd0, 5047 "\x3f\x00")), 5048 }, 5049 [ITEM_VXLAN_GPE] = { 5050 .name = "vxlan-gpe", 5051 .help = "match VXLAN-GPE header", 5052 .priv = PRIV_ITEM(VXLAN_GPE, 5053 sizeof(struct rte_flow_item_vxlan_gpe)), 5054 .next = NEXT(item_vxlan_gpe), 5055 .call = parse_vc, 5056 }, 5057 [ITEM_VXLAN_GPE_VNI] = { 5058 .name = "vni", 5059 .help = "VXLAN-GPE identifier", 5060 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED), 5061 item_param), 5062 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe, 5063 hdr.vni)), 5064 }, 5065 [ITEM_VXLAN_GPE_PROTO] = { 5066 .name = "protocol", 5067 .help = "VXLAN-GPE next protocol", 5068 .next = NEXT(item_vxlan_gpe, NEXT_ENTRY(COMMON_UNSIGNED), 5069 item_param), 5070 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_vxlan_gpe, 5071 protocol)), 5072 }, 5073 [ITEM_ARP_ETH_IPV4] = { 5074 .name = "arp_eth_ipv4", 5075 .help = "match ARP header for Ethernet/IPv4", 5076 .priv = PRIV_ITEM(ARP_ETH_IPV4, 5077 sizeof(struct rte_flow_item_arp_eth_ipv4)), 5078 .next = NEXT(item_arp_eth_ipv4), 5079 .call = parse_vc, 5080 }, 5081 [ITEM_ARP_ETH_IPV4_SHA] = { 5082 .name = "sha", 5083 .help = "sender hardware address", 5084 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR), 5085 item_param), 5086 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4, 5087 hdr.arp_data.arp_sha)), 5088 }, 5089 [ITEM_ARP_ETH_IPV4_SPA] = { 5090 .name = "spa", 5091 .help = "sender IPv4 address", 5092 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR), 5093 item_param), 5094 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4, 5095 hdr.arp_data.arp_sip)), 5096 }, 5097 [ITEM_ARP_ETH_IPV4_THA] = { 5098 .name = "tha", 5099 .help = "target hardware address", 5100 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_MAC_ADDR), 5101 item_param), 5102 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4, 5103 hdr.arp_data.arp_tha)), 5104 }, 5105 [ITEM_ARP_ETH_IPV4_TPA] = { 5106 .name = "tpa", 5107 .help = "target IPv4 address", 5108 .next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(COMMON_IPV4_ADDR), 5109 item_param), 5110 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4, 5111 hdr.arp_data.arp_tip)), 5112 }, 5113 [ITEM_IPV6_EXT] = { 5114 .name = "ipv6_ext", 5115 .help = "match presence of any IPv6 extension header", 5116 .priv = PRIV_ITEM(IPV6_EXT, 5117 sizeof(struct rte_flow_item_ipv6_ext)), 5118 .next = NEXT(item_ipv6_ext), 5119 .call = parse_vc, 5120 }, 5121 [ITEM_IPV6_EXT_NEXT_HDR] = { 5122 .name = "next_hdr", 5123 .help = "next header", 5124 .next = NEXT(item_ipv6_ext, NEXT_ENTRY(COMMON_UNSIGNED), 5125 item_param), 5126 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext, 5127 next_hdr)), 5128 }, 5129 [ITEM_IPV6_FRAG_EXT] = { 5130 .name = "ipv6_frag_ext", 5131 .help = "match presence of IPv6 fragment extension header", 5132 .priv = PRIV_ITEM(IPV6_FRAG_EXT, 5133 sizeof(struct rte_flow_item_ipv6_frag_ext)), 5134 .next = NEXT(item_ipv6_frag_ext), 5135 .call = parse_vc, 5136 }, 5137 [ITEM_IPV6_FRAG_EXT_NEXT_HDR] = { 5138 .name = "next_hdr", 5139 .help = "next header", 5140 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED), 5141 item_param), 5142 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ipv6_frag_ext, 5143 hdr.next_header)), 5144 }, 5145 [ITEM_IPV6_FRAG_EXT_FRAG_DATA] = { 5146 .name = "frag_data", 5147 .help = "fragment flags and offset", 5148 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED), 5149 item_param), 5150 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext, 5151 hdr.frag_data)), 5152 }, 5153 [ITEM_IPV6_FRAG_EXT_ID] = { 5154 .name = "packet_id", 5155 .help = "fragment packet id", 5156 .next = NEXT(item_ipv6_frag_ext, NEXT_ENTRY(COMMON_UNSIGNED), 5157 item_param), 5158 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_frag_ext, 5159 hdr.id)), 5160 }, 5161 [ITEM_ICMP6] = { 5162 .name = "icmp6", 5163 .help = "match any ICMPv6 header", 5164 .priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)), 5165 .next = NEXT(item_icmp6), 5166 .call = parse_vc, 5167 }, 5168 [ITEM_ICMP6_TYPE] = { 5169 .name = "type", 5170 .help = "ICMPv6 type", 5171 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED), 5172 item_param), 5173 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6, 5174 type)), 5175 }, 5176 [ITEM_ICMP6_CODE] = { 5177 .name = "code", 5178 .help = "ICMPv6 code", 5179 .next = NEXT(item_icmp6, NEXT_ENTRY(COMMON_UNSIGNED), 5180 item_param), 5181 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6, 5182 code)), 5183 }, 5184 [ITEM_ICMP6_ECHO_REQUEST] = { 5185 .name = "icmp6_echo_request", 5186 .help = "match ICMPv6 echo request", 5187 .priv = PRIV_ITEM(ICMP6_ECHO_REQUEST, 5188 sizeof(struct rte_flow_item_icmp6_echo)), 5189 .next = NEXT(item_icmp6_echo_request), 5190 .call = parse_vc, 5191 }, 5192 [ITEM_ICMP6_ECHO_REQUEST_ID] = { 5193 .name = "ident", 5194 .help = "ICMPv6 echo request identifier", 5195 .next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED), 5196 item_param), 5197 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo, 5198 hdr.identifier)), 5199 }, 5200 [ITEM_ICMP6_ECHO_REQUEST_SEQ] = { 5201 .name = "seq", 5202 .help = "ICMPv6 echo request sequence", 5203 .next = NEXT(item_icmp6_echo_request, NEXT_ENTRY(COMMON_UNSIGNED), 5204 item_param), 5205 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo, 5206 hdr.sequence)), 5207 }, 5208 [ITEM_ICMP6_ECHO_REPLY] = { 5209 .name = "icmp6_echo_reply", 5210 .help = "match ICMPv6 echo reply", 5211 .priv = PRIV_ITEM(ICMP6_ECHO_REPLY, 5212 sizeof(struct rte_flow_item_icmp6_echo)), 5213 .next = NEXT(item_icmp6_echo_reply), 5214 .call = parse_vc, 5215 }, 5216 [ITEM_ICMP6_ECHO_REPLY_ID] = { 5217 .name = "ident", 5218 .help = "ICMPv6 echo reply identifier", 5219 .next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED), 5220 item_param), 5221 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo, 5222 hdr.identifier)), 5223 }, 5224 [ITEM_ICMP6_ECHO_REPLY_SEQ] = { 5225 .name = "seq", 5226 .help = "ICMPv6 echo reply sequence", 5227 .next = NEXT(item_icmp6_echo_reply, NEXT_ENTRY(COMMON_UNSIGNED), 5228 item_param), 5229 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_echo, 5230 hdr.sequence)), 5231 }, 5232 [ITEM_ICMP6_ND_NS] = { 5233 .name = "icmp6_nd_ns", 5234 .help = "match ICMPv6 neighbor discovery solicitation", 5235 .priv = PRIV_ITEM(ICMP6_ND_NS, 5236 sizeof(struct rte_flow_item_icmp6_nd_ns)), 5237 .next = NEXT(item_icmp6_nd_ns), 5238 .call = parse_vc, 5239 }, 5240 [ITEM_ICMP6_ND_NS_TARGET_ADDR] = { 5241 .name = "target_addr", 5242 .help = "target address", 5243 .next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(COMMON_IPV6_ADDR), 5244 item_param), 5245 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns, 5246 target_addr)), 5247 }, 5248 [ITEM_ICMP6_ND_NA] = { 5249 .name = "icmp6_nd_na", 5250 .help = "match ICMPv6 neighbor discovery advertisement", 5251 .priv = PRIV_ITEM(ICMP6_ND_NA, 5252 sizeof(struct rte_flow_item_icmp6_nd_na)), 5253 .next = NEXT(item_icmp6_nd_na), 5254 .call = parse_vc, 5255 }, 5256 [ITEM_ICMP6_ND_NA_TARGET_ADDR] = { 5257 .name = "target_addr", 5258 .help = "target address", 5259 .next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(COMMON_IPV6_ADDR), 5260 item_param), 5261 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na, 5262 target_addr)), 5263 }, 5264 [ITEM_ICMP6_ND_OPT] = { 5265 .name = "icmp6_nd_opt", 5266 .help = "match presence of any ICMPv6 neighbor discovery" 5267 " option", 5268 .priv = PRIV_ITEM(ICMP6_ND_OPT, 5269 sizeof(struct rte_flow_item_icmp6_nd_opt)), 5270 .next = NEXT(item_icmp6_nd_opt), 5271 .call = parse_vc, 5272 }, 5273 [ITEM_ICMP6_ND_OPT_TYPE] = { 5274 .name = "type", 5275 .help = "ND option type", 5276 .next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(COMMON_UNSIGNED), 5277 item_param), 5278 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt, 5279 type)), 5280 }, 5281 [ITEM_ICMP6_ND_OPT_SLA_ETH] = { 5282 .name = "icmp6_nd_opt_sla_eth", 5283 .help = "match ICMPv6 neighbor discovery source Ethernet" 5284 " link-layer address option", 5285 .priv = PRIV_ITEM 5286 (ICMP6_ND_OPT_SLA_ETH, 5287 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)), 5288 .next = NEXT(item_icmp6_nd_opt_sla_eth), 5289 .call = parse_vc, 5290 }, 5291 [ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = { 5292 .name = "sla", 5293 .help = "source Ethernet LLA", 5294 .next = NEXT(item_icmp6_nd_opt_sla_eth, 5295 NEXT_ENTRY(COMMON_MAC_ADDR), item_param), 5296 .args = ARGS(ARGS_ENTRY_HTON 5297 (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)), 5298 }, 5299 [ITEM_ICMP6_ND_OPT_TLA_ETH] = { 5300 .name = "icmp6_nd_opt_tla_eth", 5301 .help = "match ICMPv6 neighbor discovery target Ethernet" 5302 " link-layer address option", 5303 .priv = PRIV_ITEM 5304 (ICMP6_ND_OPT_TLA_ETH, 5305 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)), 5306 .next = NEXT(item_icmp6_nd_opt_tla_eth), 5307 .call = parse_vc, 5308 }, 5309 [ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = { 5310 .name = "tla", 5311 .help = "target Ethernet LLA", 5312 .next = NEXT(item_icmp6_nd_opt_tla_eth, 5313 NEXT_ENTRY(COMMON_MAC_ADDR), item_param), 5314 .args = ARGS(ARGS_ENTRY_HTON 5315 (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)), 5316 }, 5317 [ITEM_META] = { 5318 .name = "meta", 5319 .help = "match metadata header", 5320 .priv = PRIV_ITEM(META, sizeof(struct rte_flow_item_meta)), 5321 .next = NEXT(item_meta), 5322 .call = parse_vc, 5323 }, 5324 [ITEM_META_DATA] = { 5325 .name = "data", 5326 .help = "metadata value", 5327 .next = NEXT(item_meta, NEXT_ENTRY(COMMON_UNSIGNED), 5328 item_param), 5329 .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_meta, 5330 data, "\xff\xff\xff\xff")), 5331 }, 5332 [ITEM_RANDOM] = { 5333 .name = "random", 5334 .help = "match random value", 5335 .priv = PRIV_ITEM(RANDOM, sizeof(struct rte_flow_item_random)), 5336 .next = NEXT(item_random), 5337 .call = parse_vc, 5338 }, 5339 [ITEM_RANDOM_VALUE] = { 5340 .name = "value", 5341 .help = "random value", 5342 .next = NEXT(item_random, NEXT_ENTRY(COMMON_UNSIGNED), 5343 item_param), 5344 .args = ARGS(ARGS_ENTRY_MASK(struct rte_flow_item_random, 5345 value, "\xff\xff")), 5346 }, 5347 [ITEM_GRE_KEY] = { 5348 .name = "gre_key", 5349 .help = "match GRE key", 5350 .priv = PRIV_ITEM(GRE_KEY, sizeof(rte_be32_t)), 5351 .next = NEXT(item_gre_key), 5352 .call = parse_vc, 5353 }, 5354 [ITEM_GRE_KEY_VALUE] = { 5355 .name = "value", 5356 .help = "key value", 5357 .next = NEXT(item_gre_key, NEXT_ENTRY(COMMON_UNSIGNED), 5358 item_param), 5359 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)), 5360 }, 5361 [ITEM_GRE_OPTION] = { 5362 .name = "gre_option", 5363 .help = "match GRE optional fields", 5364 .priv = PRIV_ITEM(GRE_OPTION, 5365 sizeof(struct rte_flow_item_gre_opt)), 5366 .next = NEXT(item_gre_option), 5367 .call = parse_vc, 5368 }, 5369 [ITEM_GRE_OPTION_CHECKSUM] = { 5370 .name = "checksum", 5371 .help = "match GRE checksum", 5372 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED), 5373 item_param), 5374 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt, 5375 checksum_rsvd.checksum)), 5376 }, 5377 [ITEM_GRE_OPTION_KEY] = { 5378 .name = "key", 5379 .help = "match GRE key", 5380 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED), 5381 item_param), 5382 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt, 5383 key.key)), 5384 }, 5385 [ITEM_GRE_OPTION_SEQUENCE] = { 5386 .name = "sequence", 5387 .help = "match GRE sequence", 5388 .next = NEXT(item_gre_option, NEXT_ENTRY(COMMON_UNSIGNED), 5389 item_param), 5390 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gre_opt, 5391 sequence.sequence)), 5392 }, 5393 [ITEM_GTP_PSC] = { 5394 .name = "gtp_psc", 5395 .help = "match GTP extension header with type 0x85", 5396 .priv = PRIV_ITEM(GTP_PSC, 5397 sizeof(struct rte_flow_item_gtp_psc)), 5398 .next = NEXT(item_gtp_psc), 5399 .call = parse_vc, 5400 }, 5401 [ITEM_GTP_PSC_QFI] = { 5402 .name = "qfi", 5403 .help = "QoS flow identifier", 5404 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED), 5405 item_param), 5406 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc, 5407 hdr.qfi, 6)), 5408 }, 5409 [ITEM_GTP_PSC_PDU_T] = { 5410 .name = "pdu_t", 5411 .help = "PDU type", 5412 .next = NEXT(item_gtp_psc, NEXT_ENTRY(COMMON_UNSIGNED), 5413 item_param), 5414 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_item_gtp_psc, 5415 hdr.type, 4)), 5416 }, 5417 [ITEM_PPPOES] = { 5418 .name = "pppoes", 5419 .help = "match PPPoE session header", 5420 .priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)), 5421 .next = NEXT(item_pppoes), 5422 .call = parse_vc, 5423 }, 5424 [ITEM_PPPOED] = { 5425 .name = "pppoed", 5426 .help = "match PPPoE discovery header", 5427 .priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)), 5428 .next = NEXT(item_pppoed), 5429 .call = parse_vc, 5430 }, 5431 [ITEM_PPPOE_SEID] = { 5432 .name = "seid", 5433 .help = "session identifier", 5434 .next = NEXT(item_pppoes, NEXT_ENTRY(COMMON_UNSIGNED), 5435 item_param), 5436 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe, 5437 session_id)), 5438 }, 5439 [ITEM_PPPOE_PROTO_ID] = { 5440 .name = "pppoe_proto_id", 5441 .help = "match PPPoE session protocol identifier", 5442 .priv = PRIV_ITEM(PPPOE_PROTO_ID, 5443 sizeof(struct rte_flow_item_pppoe_proto_id)), 5444 .next = NEXT(item_pppoe_proto_id, NEXT_ENTRY(COMMON_UNSIGNED), 5445 item_param), 5446 .args = ARGS(ARGS_ENTRY_HTON 5447 (struct rte_flow_item_pppoe_proto_id, proto_id)), 5448 .call = parse_vc, 5449 }, 5450 [ITEM_HIGIG2] = { 5451 .name = "higig2", 5452 .help = "matches higig2 header", 5453 .priv = PRIV_ITEM(HIGIG2, 5454 sizeof(struct rte_flow_item_higig2_hdr)), 5455 .next = NEXT(item_higig2), 5456 .call = parse_vc, 5457 }, 5458 [ITEM_HIGIG2_CLASSIFICATION] = { 5459 .name = "classification", 5460 .help = "matches classification of higig2 header", 5461 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED), 5462 item_param), 5463 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr, 5464 hdr.ppt1.classification)), 5465 }, 5466 [ITEM_HIGIG2_VID] = { 5467 .name = "vid", 5468 .help = "matches vid of higig2 header", 5469 .next = NEXT(item_higig2, NEXT_ENTRY(COMMON_UNSIGNED), 5470 item_param), 5471 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_higig2_hdr, 5472 hdr.ppt1.vid)), 5473 }, 5474 [ITEM_TAG] = { 5475 .name = "tag", 5476 .help = "match tag value", 5477 .priv = PRIV_ITEM(TAG, sizeof(struct rte_flow_item_tag)), 5478 .next = NEXT(item_tag), 5479 .call = parse_vc, 5480 }, 5481 [ITEM_TAG_DATA] = { 5482 .name = "data", 5483 .help = "tag value to match", 5484 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 5485 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, data)), 5486 }, 5487 [ITEM_TAG_INDEX] = { 5488 .name = "index", 5489 .help = "index of tag array to match", 5490 .next = NEXT(item_tag, NEXT_ENTRY(COMMON_UNSIGNED), 5491 NEXT_ENTRY(ITEM_PARAM_IS)), 5492 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tag, index)), 5493 }, 5494 [ITEM_L2TPV3OIP] = { 5495 .name = "l2tpv3oip", 5496 .help = "match L2TPv3 over IP header", 5497 .priv = PRIV_ITEM(L2TPV3OIP, 5498 sizeof(struct rte_flow_item_l2tpv3oip)), 5499 .next = NEXT(item_l2tpv3oip), 5500 .call = parse_vc, 5501 }, 5502 [ITEM_L2TPV3OIP_SESSION_ID] = { 5503 .name = "session_id", 5504 .help = "session identifier", 5505 .next = NEXT(item_l2tpv3oip, NEXT_ENTRY(COMMON_UNSIGNED), 5506 item_param), 5507 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv3oip, 5508 session_id)), 5509 }, 5510 [ITEM_ESP] = { 5511 .name = "esp", 5512 .help = "match ESP header", 5513 .priv = PRIV_ITEM(ESP, sizeof(struct rte_flow_item_esp)), 5514 .next = NEXT(item_esp), 5515 .call = parse_vc, 5516 }, 5517 [ITEM_ESP_SPI] = { 5518 .name = "spi", 5519 .help = "security policy index", 5520 .next = NEXT(item_esp, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 5521 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_esp, 5522 hdr.spi)), 5523 }, 5524 [ITEM_AH] = { 5525 .name = "ah", 5526 .help = "match AH header", 5527 .priv = PRIV_ITEM(AH, sizeof(struct rte_flow_item_ah)), 5528 .next = NEXT(item_ah), 5529 .call = parse_vc, 5530 }, 5531 [ITEM_AH_SPI] = { 5532 .name = "spi", 5533 .help = "security parameters index", 5534 .next = NEXT(item_ah, NEXT_ENTRY(COMMON_UNSIGNED), item_param), 5535 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ah, spi)), 5536 }, 5537 [ITEM_PFCP] = { 5538 .name = "pfcp", 5539 .help = "match pfcp header", 5540 .priv = PRIV_ITEM(PFCP, sizeof(struct rte_flow_item_pfcp)), 5541 .next = NEXT(item_pfcp), 5542 .call = parse_vc, 5543 }, 5544 [ITEM_PFCP_S_FIELD] = { 5545 .name = "s_field", 5546 .help = "S field", 5547 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED), 5548 item_param), 5549 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, 5550 s_field)), 5551 }, 5552 [ITEM_PFCP_SEID] = { 5553 .name = "seid", 5554 .help = "session endpoint identifier", 5555 .next = NEXT(item_pfcp, NEXT_ENTRY(COMMON_UNSIGNED), 5556 item_param), 5557 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pfcp, seid)), 5558 }, 5559 [ITEM_ECPRI] = { 5560 .name = "ecpri", 5561 .help = "match eCPRI header", 5562 .priv = PRIV_ITEM(ECPRI, sizeof(struct rte_flow_item_ecpri)), 5563 .next = NEXT(item_ecpri), 5564 .call = parse_vc, 5565 }, 5566 [ITEM_ECPRI_COMMON] = { 5567 .name = "common", 5568 .help = "eCPRI common header", 5569 .next = NEXT(item_ecpri_common), 5570 }, 5571 [ITEM_ECPRI_COMMON_TYPE] = { 5572 .name = "type", 5573 .help = "type of common header", 5574 .next = NEXT(item_ecpri_common_type), 5575 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_ecpri)), 5576 }, 5577 [ITEM_ECPRI_COMMON_TYPE_IQ_DATA] = { 5578 .name = "iq_data", 5579 .help = "Type #0: IQ Data", 5580 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID, 5581 ITEM_NEXT)), 5582 .call = parse_vc_item_ecpri_type, 5583 }, 5584 [ITEM_ECPRI_MSG_IQ_DATA_PCID] = { 5585 .name = "pc_id", 5586 .help = "Physical Channel ID", 5587 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_IQ_DATA_PCID, 5588 ITEM_ECPRI_COMMON, ITEM_NEXT), 5589 NEXT_ENTRY(COMMON_UNSIGNED), item_param), 5590 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri, 5591 hdr.type0.pc_id)), 5592 }, 5593 [ITEM_ECPRI_COMMON_TYPE_RTC_CTRL] = { 5594 .name = "rtc_ctrl", 5595 .help = "Type #2: Real-Time Control Data", 5596 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID, 5597 ITEM_NEXT)), 5598 .call = parse_vc_item_ecpri_type, 5599 }, 5600 [ITEM_ECPRI_MSG_RTC_CTRL_RTCID] = { 5601 .name = "rtc_id", 5602 .help = "Real-Time Control Data ID", 5603 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_RTC_CTRL_RTCID, 5604 ITEM_ECPRI_COMMON, ITEM_NEXT), 5605 NEXT_ENTRY(COMMON_UNSIGNED), item_param), 5606 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri, 5607 hdr.type2.rtc_id)), 5608 }, 5609 [ITEM_ECPRI_COMMON_TYPE_DLY_MSR] = { 5610 .name = "delay_measure", 5611 .help = "Type #5: One-Way Delay Measurement", 5612 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID, 5613 ITEM_NEXT)), 5614 .call = parse_vc_item_ecpri_type, 5615 }, 5616 [ITEM_ECPRI_MSG_DLY_MSR_MSRID] = { 5617 .name = "msr_id", 5618 .help = "Measurement ID", 5619 .next = NEXT(NEXT_ENTRY(ITEM_ECPRI_MSG_DLY_MSR_MSRID, 5620 ITEM_ECPRI_COMMON, ITEM_NEXT), 5621 NEXT_ENTRY(COMMON_UNSIGNED), item_param), 5622 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ecpri, 5623 hdr.type5.msr_id)), 5624 }, 5625 [ITEM_GENEVE_OPT] = { 5626 .name = "geneve-opt", 5627 .help = "GENEVE header option", 5628 .priv = PRIV_ITEM(GENEVE_OPT, 5629 sizeof(struct rte_flow_item_geneve_opt) + 5630 ITEM_GENEVE_OPT_DATA_SIZE), 5631 .next = NEXT(item_geneve_opt), 5632 .call = parse_vc, 5633 }, 5634 [ITEM_GENEVE_OPT_CLASS] = { 5635 .name = "class", 5636 .help = "GENEVE option class", 5637 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED), 5638 item_param), 5639 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve_opt, 5640 option_class)), 5641 }, 5642 [ITEM_GENEVE_OPT_TYPE] = { 5643 .name = "type", 5644 .help = "GENEVE option type", 5645 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED), 5646 item_param), 5647 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, 5648 option_type)), 5649 }, 5650 [ITEM_GENEVE_OPT_LENGTH] = { 5651 .name = "length", 5652 .help = "GENEVE option data length (in 32b words)", 5653 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_UNSIGNED), 5654 item_param), 5655 .args = ARGS(ARGS_ENTRY_BOUNDED( 5656 struct rte_flow_item_geneve_opt, option_len, 5657 0, 31)), 5658 }, 5659 [ITEM_GENEVE_OPT_DATA] = { 5660 .name = "data", 5661 .help = "GENEVE option data pattern", 5662 .next = NEXT(item_geneve_opt, NEXT_ENTRY(COMMON_HEX), 5663 item_param), 5664 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_geneve_opt, data), 5665 ARGS_ENTRY_ARB(0, 0), 5666 ARGS_ENTRY_ARB 5667 (sizeof(struct rte_flow_item_geneve_opt), 5668 ITEM_GENEVE_OPT_DATA_SIZE)), 5669 }, 5670 [ITEM_INTEGRITY] = { 5671 .name = "integrity", 5672 .help = "match packet integrity", 5673 .priv = PRIV_ITEM(INTEGRITY, 5674 sizeof(struct rte_flow_item_integrity)), 5675 .next = NEXT(item_integrity), 5676 .call = parse_vc, 5677 }, 5678 [ITEM_INTEGRITY_LEVEL] = { 5679 .name = "level", 5680 .help = "integrity level", 5681 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED), 5682 item_param), 5683 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, level)), 5684 }, 5685 [ITEM_INTEGRITY_VALUE] = { 5686 .name = "value", 5687 .help = "integrity value", 5688 .next = NEXT(item_integrity_lv, NEXT_ENTRY(COMMON_UNSIGNED), 5689 item_param), 5690 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_integrity, value)), 5691 }, 5692 [ITEM_CONNTRACK] = { 5693 .name = "conntrack", 5694 .help = "conntrack state", 5695 .next = NEXT(NEXT_ENTRY(ITEM_NEXT), NEXT_ENTRY(COMMON_UNSIGNED), 5696 item_param), 5697 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)), 5698 }, 5699 [ITEM_PORT_REPRESENTOR] = { 5700 .name = "port_representor", 5701 .help = "match traffic entering the embedded switch from the given ethdev", 5702 .priv = PRIV_ITEM(PORT_REPRESENTOR, 5703 sizeof(struct rte_flow_item_ethdev)), 5704 .next = NEXT(item_port_representor), 5705 .call = parse_vc, 5706 }, 5707 [ITEM_PORT_REPRESENTOR_PORT_ID] = { 5708 .name = "port_id", 5709 .help = "ethdev port ID", 5710 .next = NEXT(item_port_representor, NEXT_ENTRY(COMMON_UNSIGNED), 5711 item_param), 5712 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)), 5713 }, 5714 [ITEM_REPRESENTED_PORT] = { 5715 .name = "represented_port", 5716 .help = "match traffic entering the embedded switch from the entity represented by the given ethdev", 5717 .priv = PRIV_ITEM(REPRESENTED_PORT, 5718 sizeof(struct rte_flow_item_ethdev)), 5719 .next = NEXT(item_represented_port), 5720 .call = parse_vc, 5721 }, 5722 [ITEM_REPRESENTED_PORT_ETHDEV_PORT_ID] = { 5723 .name = "ethdev_port_id", 5724 .help = "ethdev port ID", 5725 .next = NEXT(item_represented_port, NEXT_ENTRY(COMMON_UNSIGNED), 5726 item_param), 5727 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ethdev, port_id)), 5728 }, 5729 [ITEM_FLEX] = { 5730 .name = "flex", 5731 .help = "match flex header", 5732 .priv = PRIV_ITEM(FLEX, sizeof(struct rte_flow_item_flex)), 5733 .next = NEXT(item_flex), 5734 .call = parse_vc, 5735 }, 5736 [ITEM_FLEX_ITEM_HANDLE] = { 5737 .name = "item", 5738 .help = "flex item handle", 5739 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE), 5740 NEXT_ENTRY(ITEM_PARAM_IS)), 5741 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, handle)), 5742 }, 5743 [ITEM_FLEX_PATTERN_HANDLE] = { 5744 .name = "pattern", 5745 .help = "flex pattern handle", 5746 .next = NEXT(item_flex, NEXT_ENTRY(COMMON_FLEX_HANDLE), 5747 NEXT_ENTRY(ITEM_PARAM_IS)), 5748 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_flex, pattern)), 5749 }, 5750 [ITEM_L2TPV2] = { 5751 .name = "l2tpv2", 5752 .help = "match L2TPv2 header", 5753 .priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)), 5754 .next = NEXT(item_l2tpv2), 5755 .call = parse_vc, 5756 }, 5757 [ITEM_L2TPV2_TYPE] = { 5758 .name = "type", 5759 .help = "type of l2tpv2", 5760 .next = NEXT(item_l2tpv2_type), 5761 .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)), 5762 }, 5763 [ITEM_L2TPV2_TYPE_DATA] = { 5764 .name = "data", 5765 .help = "Type #7: data message without any options", 5766 .next = NEXT(item_l2tpv2_type_data), 5767 .call = parse_vc_item_l2tpv2_type, 5768 }, 5769 [ITEM_L2TPV2_MSG_DATA_TUNNEL_ID] = { 5770 .name = "tunnel_id", 5771 .help = "tunnel identifier", 5772 .next = NEXT(item_l2tpv2_type_data, 5773 NEXT_ENTRY(COMMON_UNSIGNED), 5774 item_param), 5775 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5776 hdr.type7.tunnel_id)), 5777 }, 5778 [ITEM_L2TPV2_MSG_DATA_SESSION_ID] = { 5779 .name = "session_id", 5780 .help = "session identifier", 5781 .next = NEXT(item_l2tpv2_type_data, 5782 NEXT_ENTRY(COMMON_UNSIGNED), 5783 item_param), 5784 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5785 hdr.type7.session_id)), 5786 }, 5787 [ITEM_L2TPV2_TYPE_DATA_L] = { 5788 .name = "data_l", 5789 .help = "Type #6: data message with length option", 5790 .next = NEXT(item_l2tpv2_type_data_l), 5791 .call = parse_vc_item_l2tpv2_type, 5792 }, 5793 [ITEM_L2TPV2_MSG_DATA_L_LENGTH] = { 5794 .name = "length", 5795 .help = "message length", 5796 .next = NEXT(item_l2tpv2_type_data_l, 5797 NEXT_ENTRY(COMMON_UNSIGNED), 5798 item_param), 5799 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5800 hdr.type6.length)), 5801 }, 5802 [ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = { 5803 .name = "tunnel_id", 5804 .help = "tunnel identifier", 5805 .next = NEXT(item_l2tpv2_type_data_l, 5806 NEXT_ENTRY(COMMON_UNSIGNED), 5807 item_param), 5808 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5809 hdr.type6.tunnel_id)), 5810 }, 5811 [ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = { 5812 .name = "session_id", 5813 .help = "session identifier", 5814 .next = NEXT(item_l2tpv2_type_data_l, 5815 NEXT_ENTRY(COMMON_UNSIGNED), 5816 item_param), 5817 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5818 hdr.type6.session_id)), 5819 }, 5820 [ITEM_L2TPV2_TYPE_DATA_S] = { 5821 .name = "data_s", 5822 .help = "Type #5: data message with ns, nr option", 5823 .next = NEXT(item_l2tpv2_type_data_s), 5824 .call = parse_vc_item_l2tpv2_type, 5825 }, 5826 [ITEM_L2TPV2_MSG_DATA_S_TUNNEL_ID] = { 5827 .name = "tunnel_id", 5828 .help = "tunnel identifier", 5829 .next = NEXT(item_l2tpv2_type_data_s, 5830 NEXT_ENTRY(COMMON_UNSIGNED), 5831 item_param), 5832 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5833 hdr.type5.tunnel_id)), 5834 }, 5835 [ITEM_L2TPV2_MSG_DATA_S_SESSION_ID] = { 5836 .name = "session_id", 5837 .help = "session identifier", 5838 .next = NEXT(item_l2tpv2_type_data_s, 5839 NEXT_ENTRY(COMMON_UNSIGNED), 5840 item_param), 5841 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5842 hdr.type5.session_id)), 5843 }, 5844 [ITEM_L2TPV2_MSG_DATA_S_NS] = { 5845 .name = "ns", 5846 .help = "sequence number for message", 5847 .next = NEXT(item_l2tpv2_type_data_s, 5848 NEXT_ENTRY(COMMON_UNSIGNED), 5849 item_param), 5850 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5851 hdr.type5.ns)), 5852 }, 5853 [ITEM_L2TPV2_MSG_DATA_S_NR] = { 5854 .name = "nr", 5855 .help = "sequence number for next receive message", 5856 .next = NEXT(item_l2tpv2_type_data_s, 5857 NEXT_ENTRY(COMMON_UNSIGNED), 5858 item_param), 5859 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5860 hdr.type5.nr)), 5861 }, 5862 [ITEM_L2TPV2_TYPE_DATA_O] = { 5863 .name = "data_o", 5864 .help = "Type #4: data message with offset option", 5865 .next = NEXT(item_l2tpv2_type_data_o), 5866 .call = parse_vc_item_l2tpv2_type, 5867 }, 5868 [ITEM_L2TPV2_MSG_DATA_O_TUNNEL_ID] = { 5869 .name = "tunnel_id", 5870 .help = "tunnel identifier", 5871 .next = NEXT(item_l2tpv2_type_data_o, 5872 NEXT_ENTRY(COMMON_UNSIGNED), 5873 item_param), 5874 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5875 hdr.type4.tunnel_id)), 5876 }, 5877 [ITEM_L2TPV2_MSG_DATA_O_SESSION_ID] = { 5878 .name = "session_id", 5879 .help = "session identifier", 5880 .next = NEXT(item_l2tpv2_type_data_o, 5881 NEXT_ENTRY(COMMON_UNSIGNED), 5882 item_param), 5883 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5884 hdr.type5.session_id)), 5885 }, 5886 [ITEM_L2TPV2_MSG_DATA_O_OFFSET] = { 5887 .name = "offset_size", 5888 .help = "the size of offset padding", 5889 .next = NEXT(item_l2tpv2_type_data_o, 5890 NEXT_ENTRY(COMMON_UNSIGNED), 5891 item_param), 5892 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5893 hdr.type4.offset_size)), 5894 }, 5895 [ITEM_L2TPV2_TYPE_DATA_L_S] = { 5896 .name = "data_l_s", 5897 .help = "Type #3: data message contains length, ns, nr " 5898 "options", 5899 .next = NEXT(item_l2tpv2_type_data_l_s), 5900 .call = parse_vc_item_l2tpv2_type, 5901 }, 5902 [ITEM_L2TPV2_MSG_DATA_L_S_LENGTH] = { 5903 .name = "length", 5904 .help = "message length", 5905 .next = NEXT(item_l2tpv2_type_data_l_s, 5906 NEXT_ENTRY(COMMON_UNSIGNED), 5907 item_param), 5908 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5909 hdr.type3.length)), 5910 }, 5911 [ITEM_L2TPV2_MSG_DATA_L_S_TUNNEL_ID] = { 5912 .name = "tunnel_id", 5913 .help = "tunnel identifier", 5914 .next = NEXT(item_l2tpv2_type_data_l_s, 5915 NEXT_ENTRY(COMMON_UNSIGNED), 5916 item_param), 5917 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5918 hdr.type3.tunnel_id)), 5919 }, 5920 [ITEM_L2TPV2_MSG_DATA_L_S_SESSION_ID] = { 5921 .name = "session_id", 5922 .help = "session identifier", 5923 .next = NEXT(item_l2tpv2_type_data_l_s, 5924 NEXT_ENTRY(COMMON_UNSIGNED), 5925 item_param), 5926 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5927 hdr.type3.session_id)), 5928 }, 5929 [ITEM_L2TPV2_MSG_DATA_L_S_NS] = { 5930 .name = "ns", 5931 .help = "sequence number for message", 5932 .next = NEXT(item_l2tpv2_type_data_l_s, 5933 NEXT_ENTRY(COMMON_UNSIGNED), 5934 item_param), 5935 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5936 hdr.type3.ns)), 5937 }, 5938 [ITEM_L2TPV2_MSG_DATA_L_S_NR] = { 5939 .name = "nr", 5940 .help = "sequence number for next receive message", 5941 .next = NEXT(item_l2tpv2_type_data_l_s, 5942 NEXT_ENTRY(COMMON_UNSIGNED), 5943 item_param), 5944 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5945 hdr.type3.nr)), 5946 }, 5947 [ITEM_L2TPV2_TYPE_CTRL] = { 5948 .name = "control", 5949 .help = "Type #3: conrtol message contains length, ns, nr " 5950 "options", 5951 .next = NEXT(item_l2tpv2_type_ctrl), 5952 .call = parse_vc_item_l2tpv2_type, 5953 }, 5954 [ITEM_L2TPV2_MSG_CTRL_LENGTH] = { 5955 .name = "length", 5956 .help = "message length", 5957 .next = NEXT(item_l2tpv2_type_ctrl, 5958 NEXT_ENTRY(COMMON_UNSIGNED), 5959 item_param), 5960 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5961 hdr.type3.length)), 5962 }, 5963 [ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = { 5964 .name = "tunnel_id", 5965 .help = "tunnel identifier", 5966 .next = NEXT(item_l2tpv2_type_ctrl, 5967 NEXT_ENTRY(COMMON_UNSIGNED), 5968 item_param), 5969 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5970 hdr.type3.tunnel_id)), 5971 }, 5972 [ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = { 5973 .name = "session_id", 5974 .help = "session identifier", 5975 .next = NEXT(item_l2tpv2_type_ctrl, 5976 NEXT_ENTRY(COMMON_UNSIGNED), 5977 item_param), 5978 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5979 hdr.type3.session_id)), 5980 }, 5981 [ITEM_L2TPV2_MSG_CTRL_NS] = { 5982 .name = "ns", 5983 .help = "sequence number for message", 5984 .next = NEXT(item_l2tpv2_type_ctrl, 5985 NEXT_ENTRY(COMMON_UNSIGNED), 5986 item_param), 5987 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5988 hdr.type3.ns)), 5989 }, 5990 [ITEM_L2TPV2_MSG_CTRL_NR] = { 5991 .name = "nr", 5992 .help = "sequence number for next receive message", 5993 .next = NEXT(item_l2tpv2_type_ctrl, 5994 NEXT_ENTRY(COMMON_UNSIGNED), 5995 item_param), 5996 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, 5997 hdr.type3.nr)), 5998 }, 5999 [ITEM_PPP] = { 6000 .name = "ppp", 6001 .help = "match PPP header", 6002 .priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)), 6003 .next = NEXT(item_ppp), 6004 .call = parse_vc, 6005 }, 6006 [ITEM_PPP_ADDR] = { 6007 .name = "addr", 6008 .help = "PPP address", 6009 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED), 6010 item_param), 6011 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.addr)), 6012 }, 6013 [ITEM_PPP_CTRL] = { 6014 .name = "ctrl", 6015 .help = "PPP control", 6016 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED), 6017 item_param), 6018 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, hdr.ctrl)), 6019 }, 6020 [ITEM_PPP_PROTO_ID] = { 6021 .name = "proto_id", 6022 .help = "PPP protocol identifier", 6023 .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED), 6024 item_param), 6025 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, 6026 hdr.proto_id)), 6027 }, 6028 [ITEM_METER] = { 6029 .name = "meter", 6030 .help = "match meter color", 6031 .priv = PRIV_ITEM(METER_COLOR, 6032 sizeof(struct rte_flow_item_meter_color)), 6033 .next = NEXT(item_meter), 6034 .call = parse_vc, 6035 }, 6036 [ITEM_METER_COLOR] = { 6037 .name = "color", 6038 .help = "meter color", 6039 .next = NEXT(item_meter, 6040 NEXT_ENTRY(ITEM_METER_COLOR_NAME), 6041 item_param), 6042 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_meter_color, 6043 color)), 6044 }, 6045 [ITEM_METER_COLOR_NAME] = { 6046 .name = "color_name", 6047 .help = "meter color name", 6048 .call = parse_meter_color, 6049 .comp = comp_meter_color, 6050 }, 6051 [ITEM_QUOTA] = { 6052 .name = "quota", 6053 .help = "match quota", 6054 .priv = PRIV_ITEM(QUOTA, sizeof(struct rte_flow_item_quota)), 6055 .next = NEXT(item_quota), 6056 .call = parse_vc 6057 }, 6058 [ITEM_QUOTA_STATE] = { 6059 .name = "quota_state", 6060 .help = "quota state", 6061 .next = NEXT(item_quota, NEXT_ENTRY(ITEM_QUOTA_STATE_NAME), 6062 NEXT_ENTRY(ITEM_PARAM_SPEC, ITEM_PARAM_MASK)), 6063 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_quota, state)) 6064 }, 6065 [ITEM_QUOTA_STATE_NAME] = { 6066 .name = "state_name", 6067 .help = "quota state name", 6068 .call = parse_quota_state_name, 6069 .comp = comp_quota_state_name 6070 }, 6071 [ITEM_IB_BTH] = { 6072 .name = "ib_bth", 6073 .help = "match ib bth fields", 6074 .priv = PRIV_ITEM(IB_BTH, 6075 sizeof(struct rte_flow_item_ib_bth)), 6076 .next = NEXT(item_ib_bth), 6077 .call = parse_vc, 6078 }, 6079 [ITEM_IB_BTH_OPCODE] = { 6080 .name = "opcode", 6081 .help = "match ib bth opcode", 6082 .next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED), 6083 item_param), 6084 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth, 6085 hdr.opcode)), 6086 }, 6087 [ITEM_IB_BTH_PKEY] = { 6088 .name = "pkey", 6089 .help = "partition key", 6090 .next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED), 6091 item_param), 6092 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth, 6093 hdr.pkey)), 6094 }, 6095 [ITEM_IB_BTH_DST_QPN] = { 6096 .name = "dst_qp", 6097 .help = "destination qp", 6098 .next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED), 6099 item_param), 6100 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth, 6101 hdr.dst_qp)), 6102 }, 6103 [ITEM_IB_BTH_PSN] = { 6104 .name = "psn", 6105 .help = "packet sequence number", 6106 .next = NEXT(item_ib_bth, NEXT_ENTRY(COMMON_UNSIGNED), 6107 item_param), 6108 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ib_bth, 6109 hdr.psn)), 6110 }, 6111 [ITEM_PTYPE] = { 6112 .name = "ptype", 6113 .help = "match L2/L3/L4 and tunnel information", 6114 .priv = PRIV_ITEM(PTYPE, 6115 sizeof(struct rte_flow_item_ptype)), 6116 .next = NEXT(item_ptype), 6117 .call = parse_vc, 6118 }, 6119 [ITEM_PTYPE_VALUE] = { 6120 .name = "packet_type", 6121 .help = "packet type as defined in rte_mbuf_ptype", 6122 .next = NEXT(item_ptype, NEXT_ENTRY(COMMON_UNSIGNED), 6123 item_param), 6124 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ptype, packet_type)), 6125 }, 6126 [ITEM_NSH] = { 6127 .name = "nsh", 6128 .help = "match NSH header", 6129 .priv = PRIV_ITEM(NSH, 6130 sizeof(struct rte_flow_item_nsh)), 6131 .next = NEXT(item_nsh), 6132 .call = parse_vc, 6133 }, 6134 [ITEM_COMPARE] = { 6135 .name = "compare", 6136 .help = "match with the comparison result", 6137 .priv = PRIV_ITEM(COMPARE, sizeof(struct rte_flow_item_compare)), 6138 .next = NEXT(NEXT_ENTRY(ITEM_COMPARE_OP)), 6139 .call = parse_vc, 6140 }, 6141 [ITEM_COMPARE_OP] = { 6142 .name = "op", 6143 .help = "operation type", 6144 .next = NEXT(item_compare_field, 6145 NEXT_ENTRY(ITEM_COMPARE_OP_VALUE), item_param), 6146 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, operation)), 6147 }, 6148 [ITEM_COMPARE_OP_VALUE] = { 6149 .name = "{operation}", 6150 .help = "operation type value", 6151 .call = parse_vc_compare_op, 6152 .comp = comp_set_compare_op, 6153 }, 6154 [ITEM_COMPARE_FIELD_A_TYPE] = { 6155 .name = "a_type", 6156 .help = "compared field type", 6157 .next = NEXT(compare_field_a, 6158 NEXT_ENTRY(ITEM_COMPARE_FIELD_A_TYPE_VALUE), item_param), 6159 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.field)), 6160 }, 6161 [ITEM_COMPARE_FIELD_A_TYPE_VALUE] = { 6162 .name = "{a_type}", 6163 .help = "compared field type value", 6164 .call = parse_vc_compare_field_id, 6165 .comp = comp_set_compare_field_id, 6166 }, 6167 [ITEM_COMPARE_FIELD_A_LEVEL] = { 6168 .name = "a_level", 6169 .help = "compared field level", 6170 .next = NEXT(compare_field_a, 6171 NEXT_ENTRY(ITEM_COMPARE_FIELD_A_LEVEL_VALUE), item_param), 6172 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, a.level)), 6173 }, 6174 [ITEM_COMPARE_FIELD_A_LEVEL_VALUE] = { 6175 .name = "{a_level}", 6176 .help = "compared field level value", 6177 .call = parse_vc_compare_field_level, 6178 .comp = comp_none, 6179 }, 6180 [ITEM_COMPARE_FIELD_A_TAG_INDEX] = { 6181 .name = "a_tag_index", 6182 .help = "compared field tag array", 6183 .next = NEXT(compare_field_a, 6184 NEXT_ENTRY(COMMON_UNSIGNED), item_param), 6185 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, 6186 a.tag_index)), 6187 }, 6188 [ITEM_COMPARE_FIELD_A_TYPE_ID] = { 6189 .name = "a_type_id", 6190 .help = "compared field type ID", 6191 .next = NEXT(compare_field_a, 6192 NEXT_ENTRY(COMMON_UNSIGNED), item_param), 6193 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, 6194 a.type)), 6195 }, 6196 [ITEM_COMPARE_FIELD_A_CLASS_ID] = { 6197 .name = "a_class", 6198 .help = "compared field class ID", 6199 .next = NEXT(compare_field_a, 6200 NEXT_ENTRY(COMMON_UNSIGNED), item_param), 6201 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare, 6202 a.class_id)), 6203 }, 6204 [ITEM_COMPARE_FIELD_A_OFFSET] = { 6205 .name = "a_offset", 6206 .help = "compared field bit offset", 6207 .next = NEXT(compare_field_a, 6208 NEXT_ENTRY(COMMON_UNSIGNED), item_param), 6209 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, 6210 a.offset)), 6211 }, 6212 [ITEM_COMPARE_FIELD_B_TYPE] = { 6213 .name = "b_type", 6214 .help = "comparator field type", 6215 .next = NEXT(compare_field_b, 6216 NEXT_ENTRY(ITEM_COMPARE_FIELD_B_TYPE_VALUE), item_param), 6217 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, 6218 b.field)), 6219 }, 6220 [ITEM_COMPARE_FIELD_B_TYPE_VALUE] = { 6221 .name = "{b_type}", 6222 .help = "comparator field type value", 6223 .call = parse_vc_compare_field_id, 6224 .comp = comp_set_compare_field_id, 6225 }, 6226 [ITEM_COMPARE_FIELD_B_LEVEL] = { 6227 .name = "b_level", 6228 .help = "comparator field level", 6229 .next = NEXT(compare_field_b, 6230 NEXT_ENTRY(ITEM_COMPARE_FIELD_B_LEVEL_VALUE), item_param), 6231 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, 6232 b.level)), 6233 }, 6234 [ITEM_COMPARE_FIELD_B_LEVEL_VALUE] = { 6235 .name = "{b_level}", 6236 .help = "comparator field level value", 6237 .call = parse_vc_compare_field_level, 6238 .comp = comp_none, 6239 }, 6240 [ITEM_COMPARE_FIELD_B_TAG_INDEX] = { 6241 .name = "b_tag_index", 6242 .help = "comparator field tag array", 6243 .next = NEXT(compare_field_b, 6244 NEXT_ENTRY(COMMON_UNSIGNED), item_param), 6245 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, 6246 b.tag_index)), 6247 }, 6248 [ITEM_COMPARE_FIELD_B_TYPE_ID] = { 6249 .name = "b_type_id", 6250 .help = "comparator field type ID", 6251 .next = NEXT(compare_field_b, 6252 NEXT_ENTRY(COMMON_UNSIGNED), item_param), 6253 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, 6254 b.type)), 6255 }, 6256 [ITEM_COMPARE_FIELD_B_CLASS_ID] = { 6257 .name = "b_class", 6258 .help = "comparator field class ID", 6259 .next = NEXT(compare_field_b, 6260 NEXT_ENTRY(COMMON_UNSIGNED), item_param), 6261 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_compare, 6262 b.class_id)), 6263 }, 6264 [ITEM_COMPARE_FIELD_B_OFFSET] = { 6265 .name = "b_offset", 6266 .help = "comparator field bit offset", 6267 .next = NEXT(compare_field_b, 6268 NEXT_ENTRY(COMMON_UNSIGNED), item_param), 6269 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, 6270 b.offset)), 6271 }, 6272 [ITEM_COMPARE_FIELD_B_VALUE] = { 6273 .name = "b_value", 6274 .help = "comparator immediate value", 6275 .next = NEXT(compare_field_b, 6276 NEXT_ENTRY(COMMON_HEX), item_param), 6277 .args = ARGS(ARGS_ENTRY_ARB(0, 0), 6278 ARGS_ENTRY_ARB(0, 0), 6279 ARGS_ENTRY(struct rte_flow_item_compare, 6280 b.value)), 6281 }, 6282 [ITEM_COMPARE_FIELD_B_POINTER] = { 6283 .name = "b_ptr", 6284 .help = "pointer to comparator immediate value", 6285 .next = NEXT(compare_field_b, 6286 NEXT_ENTRY(COMMON_HEX), item_param), 6287 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, 6288 b.pvalue), 6289 ARGS_ENTRY_ARB(0, 0), 6290 ARGS_ENTRY_ARB 6291 (sizeof(struct rte_flow_item_compare), 6292 FLOW_FIELD_PATTERN_SIZE)), 6293 }, 6294 [ITEM_COMPARE_FIELD_WIDTH] = { 6295 .name = "width", 6296 .help = "number of bits to compare", 6297 .next = NEXT(item_compare_field, 6298 NEXT_ENTRY(COMMON_UNSIGNED), item_param), 6299 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_compare, 6300 width)), 6301 }, 6302 6303 /* Validate/create actions. */ 6304 [ACTIONS] = { 6305 .name = "actions", 6306 .help = "submit a list of associated actions", 6307 .next = NEXT(next_action), 6308 .call = parse_vc, 6309 }, 6310 [ACTION_NEXT] = { 6311 .name = "/", 6312 .help = "specify next action", 6313 .next = NEXT(next_action), 6314 }, 6315 [ACTION_END] = { 6316 .name = "end", 6317 .help = "end list of actions", 6318 .priv = PRIV_ACTION(END, 0), 6319 .call = parse_vc, 6320 }, 6321 [ACTION_VOID] = { 6322 .name = "void", 6323 .help = "no-op action", 6324 .priv = PRIV_ACTION(VOID, 0), 6325 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6326 .call = parse_vc, 6327 }, 6328 [ACTION_PASSTHRU] = { 6329 .name = "passthru", 6330 .help = "let subsequent rule process matched packets", 6331 .priv = PRIV_ACTION(PASSTHRU, 0), 6332 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6333 .call = parse_vc, 6334 }, 6335 [ACTION_SKIP_CMAN] = { 6336 .name = "skip_cman", 6337 .help = "bypass cman on received packets", 6338 .priv = PRIV_ACTION(SKIP_CMAN, 0), 6339 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6340 .call = parse_vc, 6341 }, 6342 [ACTION_JUMP] = { 6343 .name = "jump", 6344 .help = "redirect traffic to a given group", 6345 .priv = PRIV_ACTION(JUMP, sizeof(struct rte_flow_action_jump)), 6346 .next = NEXT(action_jump), 6347 .call = parse_vc, 6348 }, 6349 [ACTION_JUMP_GROUP] = { 6350 .name = "group", 6351 .help = "group to redirect traffic to", 6352 .next = NEXT(action_jump, NEXT_ENTRY(COMMON_UNSIGNED)), 6353 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_jump, group)), 6354 .call = parse_vc_conf, 6355 }, 6356 [ACTION_MARK] = { 6357 .name = "mark", 6358 .help = "attach 32 bit value to packets", 6359 .priv = PRIV_ACTION(MARK, sizeof(struct rte_flow_action_mark)), 6360 .next = NEXT(action_mark), 6361 .call = parse_vc, 6362 }, 6363 [ACTION_MARK_ID] = { 6364 .name = "id", 6365 .help = "32 bit value to return with packets", 6366 .next = NEXT(action_mark, NEXT_ENTRY(COMMON_UNSIGNED)), 6367 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_mark, id)), 6368 .call = parse_vc_conf, 6369 }, 6370 [ACTION_FLAG] = { 6371 .name = "flag", 6372 .help = "flag packets", 6373 .priv = PRIV_ACTION(FLAG, 0), 6374 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6375 .call = parse_vc, 6376 }, 6377 [ACTION_QUEUE] = { 6378 .name = "queue", 6379 .help = "assign packets to a given queue index", 6380 .priv = PRIV_ACTION(QUEUE, 6381 sizeof(struct rte_flow_action_queue)), 6382 .next = NEXT(action_queue), 6383 .call = parse_vc, 6384 }, 6385 [ACTION_QUEUE_INDEX] = { 6386 .name = "index", 6387 .help = "queue index to use", 6388 .next = NEXT(action_queue, NEXT_ENTRY(COMMON_UNSIGNED)), 6389 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)), 6390 .call = parse_vc_conf, 6391 }, 6392 [ACTION_DROP] = { 6393 .name = "drop", 6394 .help = "drop packets (note: passthru has priority)", 6395 .priv = PRIV_ACTION(DROP, 0), 6396 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6397 .call = parse_vc, 6398 }, 6399 [ACTION_COUNT] = { 6400 .name = "count", 6401 .help = "enable counters for this rule", 6402 .priv = PRIV_ACTION(COUNT, 6403 sizeof(struct rte_flow_action_count)), 6404 .next = NEXT(action_count), 6405 .call = parse_vc, 6406 }, 6407 [ACTION_COUNT_ID] = { 6408 .name = "identifier", 6409 .help = "counter identifier to use", 6410 .next = NEXT(action_count, NEXT_ENTRY(COMMON_UNSIGNED)), 6411 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_count, id)), 6412 .call = parse_vc_conf, 6413 }, 6414 [ACTION_RSS] = { 6415 .name = "rss", 6416 .help = "spread packets among several queues", 6417 .priv = PRIV_ACTION(RSS, sizeof(struct action_rss_data)), 6418 .next = NEXT(action_rss), 6419 .call = parse_vc_action_rss, 6420 }, 6421 [ACTION_RSS_FUNC] = { 6422 .name = "func", 6423 .help = "RSS hash function to apply", 6424 .next = NEXT(action_rss, 6425 NEXT_ENTRY(ACTION_RSS_FUNC_DEFAULT, 6426 ACTION_RSS_FUNC_TOEPLITZ, 6427 ACTION_RSS_FUNC_SIMPLE_XOR, 6428 ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ)), 6429 }, 6430 [ACTION_RSS_FUNC_DEFAULT] = { 6431 .name = "default", 6432 .help = "default hash function", 6433 .call = parse_vc_action_rss_func, 6434 }, 6435 [ACTION_RSS_FUNC_TOEPLITZ] = { 6436 .name = "toeplitz", 6437 .help = "Toeplitz hash function", 6438 .call = parse_vc_action_rss_func, 6439 }, 6440 [ACTION_RSS_FUNC_SIMPLE_XOR] = { 6441 .name = "simple_xor", 6442 .help = "simple XOR hash function", 6443 .call = parse_vc_action_rss_func, 6444 }, 6445 [ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ] = { 6446 .name = "symmetric_toeplitz", 6447 .help = "Symmetric Toeplitz hash function", 6448 .call = parse_vc_action_rss_func, 6449 }, 6450 [ACTION_RSS_LEVEL] = { 6451 .name = "level", 6452 .help = "encapsulation level for \"types\"", 6453 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)), 6454 .args = ARGS(ARGS_ENTRY_ARB 6455 (offsetof(struct action_rss_data, conf) + 6456 offsetof(struct rte_flow_action_rss, level), 6457 sizeof(((struct rte_flow_action_rss *)0)-> 6458 level))), 6459 }, 6460 [ACTION_RSS_TYPES] = { 6461 .name = "types", 6462 .help = "specific RSS hash types", 6463 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)), 6464 }, 6465 [ACTION_RSS_TYPE] = { 6466 .name = "{type}", 6467 .help = "RSS hash type", 6468 .call = parse_vc_action_rss_type, 6469 .comp = comp_vc_action_rss_type, 6470 }, 6471 [ACTION_RSS_KEY] = { 6472 .name = "key", 6473 .help = "RSS hash key", 6474 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_HEX)), 6475 .args = ARGS(ARGS_ENTRY_ARB 6476 (offsetof(struct action_rss_data, conf) + 6477 offsetof(struct rte_flow_action_rss, key), 6478 sizeof(((struct rte_flow_action_rss *)0)->key)), 6479 ARGS_ENTRY_ARB 6480 (offsetof(struct action_rss_data, conf) + 6481 offsetof(struct rte_flow_action_rss, key_len), 6482 sizeof(((struct rte_flow_action_rss *)0)-> 6483 key_len)), 6484 ARGS_ENTRY(struct action_rss_data, key)), 6485 }, 6486 [ACTION_RSS_KEY_LEN] = { 6487 .name = "key_len", 6488 .help = "RSS hash key length in bytes", 6489 .next = NEXT(action_rss, NEXT_ENTRY(COMMON_UNSIGNED)), 6490 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED 6491 (offsetof(struct action_rss_data, conf) + 6492 offsetof(struct rte_flow_action_rss, key_len), 6493 sizeof(((struct rte_flow_action_rss *)0)-> 6494 key_len), 6495 0, 6496 RSS_HASH_KEY_LENGTH)), 6497 }, 6498 [ACTION_RSS_QUEUES] = { 6499 .name = "queues", 6500 .help = "queue indices to use", 6501 .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_QUEUE)), 6502 .call = parse_vc_conf, 6503 }, 6504 [ACTION_RSS_QUEUE] = { 6505 .name = "{queue}", 6506 .help = "queue index", 6507 .call = parse_vc_action_rss_queue, 6508 .comp = comp_vc_action_rss_queue, 6509 }, 6510 [ACTION_PF] = { 6511 .name = "pf", 6512 .help = "direct traffic to physical function", 6513 .priv = PRIV_ACTION(PF, 0), 6514 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6515 .call = parse_vc, 6516 }, 6517 [ACTION_VF] = { 6518 .name = "vf", 6519 .help = "direct traffic to a virtual function ID", 6520 .priv = PRIV_ACTION(VF, sizeof(struct rte_flow_action_vf)), 6521 .next = NEXT(action_vf), 6522 .call = parse_vc, 6523 }, 6524 [ACTION_VF_ORIGINAL] = { 6525 .name = "original", 6526 .help = "use original VF ID if possible", 6527 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_BOOLEAN)), 6528 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_vf, 6529 original, 1)), 6530 .call = parse_vc_conf, 6531 }, 6532 [ACTION_VF_ID] = { 6533 .name = "id", 6534 .help = "VF ID", 6535 .next = NEXT(action_vf, NEXT_ENTRY(COMMON_UNSIGNED)), 6536 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_vf, id)), 6537 .call = parse_vc_conf, 6538 }, 6539 [ACTION_PORT_ID] = { 6540 .name = "port_id", 6541 .help = "direct matching traffic to a given DPDK port ID", 6542 .priv = PRIV_ACTION(PORT_ID, 6543 sizeof(struct rte_flow_action_port_id)), 6544 .next = NEXT(action_port_id), 6545 .call = parse_vc, 6546 }, 6547 [ACTION_PORT_ID_ORIGINAL] = { 6548 .name = "original", 6549 .help = "use original DPDK port ID if possible", 6550 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_BOOLEAN)), 6551 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_port_id, 6552 original, 1)), 6553 .call = parse_vc_conf, 6554 }, 6555 [ACTION_PORT_ID_ID] = { 6556 .name = "id", 6557 .help = "DPDK port ID", 6558 .next = NEXT(action_port_id, NEXT_ENTRY(COMMON_UNSIGNED)), 6559 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_port_id, id)), 6560 .call = parse_vc_conf, 6561 }, 6562 [ACTION_METER] = { 6563 .name = "meter", 6564 .help = "meter the directed packets at given id", 6565 .priv = PRIV_ACTION(METER, 6566 sizeof(struct rte_flow_action_meter)), 6567 .next = NEXT(action_meter), 6568 .call = parse_vc, 6569 }, 6570 [ACTION_METER_COLOR] = { 6571 .name = "color", 6572 .help = "meter color for the packets", 6573 .priv = PRIV_ACTION(METER_COLOR, 6574 sizeof(struct rte_flow_action_meter_color)), 6575 .next = NEXT(action_meter_color), 6576 .call = parse_vc, 6577 }, 6578 [ACTION_METER_COLOR_TYPE] = { 6579 .name = "type", 6580 .help = "specific meter color", 6581 .next = NEXT(NEXT_ENTRY(ACTION_NEXT), 6582 NEXT_ENTRY(ACTION_METER_COLOR_GREEN, 6583 ACTION_METER_COLOR_YELLOW, 6584 ACTION_METER_COLOR_RED)), 6585 }, 6586 [ACTION_METER_COLOR_GREEN] = { 6587 .name = "green", 6588 .help = "meter color green", 6589 .call = parse_vc_action_meter_color_type, 6590 }, 6591 [ACTION_METER_COLOR_YELLOW] = { 6592 .name = "yellow", 6593 .help = "meter color yellow", 6594 .call = parse_vc_action_meter_color_type, 6595 }, 6596 [ACTION_METER_COLOR_RED] = { 6597 .name = "red", 6598 .help = "meter color red", 6599 .call = parse_vc_action_meter_color_type, 6600 }, 6601 [ACTION_METER_ID] = { 6602 .name = "mtr_id", 6603 .help = "meter id to use", 6604 .next = NEXT(action_meter, NEXT_ENTRY(COMMON_UNSIGNED)), 6605 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)), 6606 .call = parse_vc_conf, 6607 }, 6608 [ACTION_METER_MARK] = { 6609 .name = "meter_mark", 6610 .help = "meter the directed packets using profile and policy", 6611 .priv = PRIV_ACTION(METER_MARK, 6612 sizeof(struct rte_flow_action_meter_mark)), 6613 .next = NEXT(action_meter_mark), 6614 .call = parse_vc, 6615 }, 6616 [ACTION_METER_PROFILE] = { 6617 .name = "mtr_profile", 6618 .help = "meter profile id to use", 6619 .next = NEXT(NEXT_ENTRY(ACTION_METER_PROFILE_ID2PTR)), 6620 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))), 6621 }, 6622 [ACTION_METER_PROFILE_ID2PTR] = { 6623 .name = "{mtr_profile_id}", 6624 .type = "PROFILE_ID", 6625 .help = "meter profile id", 6626 .next = NEXT(action_meter_mark), 6627 .call = parse_meter_profile_id2ptr, 6628 .comp = comp_none, 6629 }, 6630 [ACTION_METER_POLICY] = { 6631 .name = "mtr_policy", 6632 .help = "meter policy id to use", 6633 .next = NEXT(NEXT_ENTRY(ACTION_METER_POLICY_ID2PTR)), 6634 ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))), 6635 }, 6636 [ACTION_METER_POLICY_ID2PTR] = { 6637 .name = "{mtr_policy_id}", 6638 .type = "POLICY_ID", 6639 .help = "meter policy id", 6640 .next = NEXT(action_meter_mark), 6641 .call = parse_meter_policy_id2ptr, 6642 .comp = comp_none, 6643 }, 6644 [ACTION_METER_COLOR_MODE] = { 6645 .name = "mtr_color_mode", 6646 .help = "meter color awareness mode", 6647 .next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)), 6648 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, color_mode)), 6649 .call = parse_vc_conf, 6650 }, 6651 [ACTION_METER_STATE] = { 6652 .name = "mtr_state", 6653 .help = "meter state", 6654 .next = NEXT(action_meter_mark, NEXT_ENTRY(COMMON_UNSIGNED)), 6655 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter_mark, state)), 6656 .call = parse_vc_conf, 6657 }, 6658 [ACTION_OF_DEC_NW_TTL] = { 6659 .name = "of_dec_nw_ttl", 6660 .help = "OpenFlow's OFPAT_DEC_NW_TTL", 6661 .priv = PRIV_ACTION(OF_DEC_NW_TTL, 0), 6662 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6663 .call = parse_vc, 6664 }, 6665 [ACTION_OF_POP_VLAN] = { 6666 .name = "of_pop_vlan", 6667 .help = "OpenFlow's OFPAT_POP_VLAN", 6668 .priv = PRIV_ACTION(OF_POP_VLAN, 0), 6669 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6670 .call = parse_vc, 6671 }, 6672 [ACTION_OF_PUSH_VLAN] = { 6673 .name = "of_push_vlan", 6674 .help = "OpenFlow's OFPAT_PUSH_VLAN", 6675 .priv = PRIV_ACTION 6676 (OF_PUSH_VLAN, 6677 sizeof(struct rte_flow_action_of_push_vlan)), 6678 .next = NEXT(action_of_push_vlan), 6679 .call = parse_vc, 6680 }, 6681 [ACTION_OF_PUSH_VLAN_ETHERTYPE] = { 6682 .name = "ethertype", 6683 .help = "EtherType", 6684 .next = NEXT(action_of_push_vlan, NEXT_ENTRY(COMMON_UNSIGNED)), 6685 .args = ARGS(ARGS_ENTRY_HTON 6686 (struct rte_flow_action_of_push_vlan, 6687 ethertype)), 6688 .call = parse_vc_conf, 6689 }, 6690 [ACTION_OF_SET_VLAN_VID] = { 6691 .name = "of_set_vlan_vid", 6692 .help = "OpenFlow's OFPAT_SET_VLAN_VID", 6693 .priv = PRIV_ACTION 6694 (OF_SET_VLAN_VID, 6695 sizeof(struct rte_flow_action_of_set_vlan_vid)), 6696 .next = NEXT(action_of_set_vlan_vid), 6697 .call = parse_vc, 6698 }, 6699 [ACTION_OF_SET_VLAN_VID_VLAN_VID] = { 6700 .name = "vlan_vid", 6701 .help = "VLAN id", 6702 .next = NEXT(action_of_set_vlan_vid, 6703 NEXT_ENTRY(COMMON_UNSIGNED)), 6704 .args = ARGS(ARGS_ENTRY_HTON 6705 (struct rte_flow_action_of_set_vlan_vid, 6706 vlan_vid)), 6707 .call = parse_vc_conf, 6708 }, 6709 [ACTION_OF_SET_VLAN_PCP] = { 6710 .name = "of_set_vlan_pcp", 6711 .help = "OpenFlow's OFPAT_SET_VLAN_PCP", 6712 .priv = PRIV_ACTION 6713 (OF_SET_VLAN_PCP, 6714 sizeof(struct rte_flow_action_of_set_vlan_pcp)), 6715 .next = NEXT(action_of_set_vlan_pcp), 6716 .call = parse_vc, 6717 }, 6718 [ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = { 6719 .name = "vlan_pcp", 6720 .help = "VLAN priority", 6721 .next = NEXT(action_of_set_vlan_pcp, 6722 NEXT_ENTRY(COMMON_UNSIGNED)), 6723 .args = ARGS(ARGS_ENTRY_HTON 6724 (struct rte_flow_action_of_set_vlan_pcp, 6725 vlan_pcp)), 6726 .call = parse_vc_conf, 6727 }, 6728 [ACTION_OF_POP_MPLS] = { 6729 .name = "of_pop_mpls", 6730 .help = "OpenFlow's OFPAT_POP_MPLS", 6731 .priv = PRIV_ACTION(OF_POP_MPLS, 6732 sizeof(struct rte_flow_action_of_pop_mpls)), 6733 .next = NEXT(action_of_pop_mpls), 6734 .call = parse_vc, 6735 }, 6736 [ACTION_OF_POP_MPLS_ETHERTYPE] = { 6737 .name = "ethertype", 6738 .help = "EtherType", 6739 .next = NEXT(action_of_pop_mpls, NEXT_ENTRY(COMMON_UNSIGNED)), 6740 .args = ARGS(ARGS_ENTRY_HTON 6741 (struct rte_flow_action_of_pop_mpls, 6742 ethertype)), 6743 .call = parse_vc_conf, 6744 }, 6745 [ACTION_OF_PUSH_MPLS] = { 6746 .name = "of_push_mpls", 6747 .help = "OpenFlow's OFPAT_PUSH_MPLS", 6748 .priv = PRIV_ACTION 6749 (OF_PUSH_MPLS, 6750 sizeof(struct rte_flow_action_of_push_mpls)), 6751 .next = NEXT(action_of_push_mpls), 6752 .call = parse_vc, 6753 }, 6754 [ACTION_OF_PUSH_MPLS_ETHERTYPE] = { 6755 .name = "ethertype", 6756 .help = "EtherType", 6757 .next = NEXT(action_of_push_mpls, NEXT_ENTRY(COMMON_UNSIGNED)), 6758 .args = ARGS(ARGS_ENTRY_HTON 6759 (struct rte_flow_action_of_push_mpls, 6760 ethertype)), 6761 .call = parse_vc_conf, 6762 }, 6763 [ACTION_VXLAN_ENCAP] = { 6764 .name = "vxlan_encap", 6765 .help = "VXLAN encapsulation, uses configuration set by \"set" 6766 " vxlan\"", 6767 .priv = PRIV_ACTION(VXLAN_ENCAP, 6768 sizeof(struct action_vxlan_encap_data)), 6769 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6770 .call = parse_vc_action_vxlan_encap, 6771 }, 6772 [ACTION_VXLAN_DECAP] = { 6773 .name = "vxlan_decap", 6774 .help = "Performs a decapsulation action by stripping all" 6775 " headers of the VXLAN tunnel network overlay from the" 6776 " matched flow.", 6777 .priv = PRIV_ACTION(VXLAN_DECAP, 0), 6778 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6779 .call = parse_vc, 6780 }, 6781 [ACTION_NVGRE_ENCAP] = { 6782 .name = "nvgre_encap", 6783 .help = "NVGRE encapsulation, uses configuration set by \"set" 6784 " nvgre\"", 6785 .priv = PRIV_ACTION(NVGRE_ENCAP, 6786 sizeof(struct action_nvgre_encap_data)), 6787 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6788 .call = parse_vc_action_nvgre_encap, 6789 }, 6790 [ACTION_NVGRE_DECAP] = { 6791 .name = "nvgre_decap", 6792 .help = "Performs a decapsulation action by stripping all" 6793 " headers of the NVGRE tunnel network overlay from the" 6794 " matched flow.", 6795 .priv = PRIV_ACTION(NVGRE_DECAP, 0), 6796 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6797 .call = parse_vc, 6798 }, 6799 [ACTION_L2_ENCAP] = { 6800 .name = "l2_encap", 6801 .help = "l2 encap, uses configuration set by" 6802 " \"set l2_encap\"", 6803 .priv = PRIV_ACTION(RAW_ENCAP, 6804 sizeof(struct action_raw_encap_data)), 6805 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6806 .call = parse_vc_action_l2_encap, 6807 }, 6808 [ACTION_L2_DECAP] = { 6809 .name = "l2_decap", 6810 .help = "l2 decap, uses configuration set by" 6811 " \"set l2_decap\"", 6812 .priv = PRIV_ACTION(RAW_DECAP, 6813 sizeof(struct action_raw_decap_data)), 6814 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6815 .call = parse_vc_action_l2_decap, 6816 }, 6817 [ACTION_MPLSOGRE_ENCAP] = { 6818 .name = "mplsogre_encap", 6819 .help = "mplsogre encapsulation, uses configuration set by" 6820 " \"set mplsogre_encap\"", 6821 .priv = PRIV_ACTION(RAW_ENCAP, 6822 sizeof(struct action_raw_encap_data)), 6823 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6824 .call = parse_vc_action_mplsogre_encap, 6825 }, 6826 [ACTION_MPLSOGRE_DECAP] = { 6827 .name = "mplsogre_decap", 6828 .help = "mplsogre decapsulation, uses configuration set by" 6829 " \"set mplsogre_decap\"", 6830 .priv = PRIV_ACTION(RAW_DECAP, 6831 sizeof(struct action_raw_decap_data)), 6832 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6833 .call = parse_vc_action_mplsogre_decap, 6834 }, 6835 [ACTION_MPLSOUDP_ENCAP] = { 6836 .name = "mplsoudp_encap", 6837 .help = "mplsoudp encapsulation, uses configuration set by" 6838 " \"set mplsoudp_encap\"", 6839 .priv = PRIV_ACTION(RAW_ENCAP, 6840 sizeof(struct action_raw_encap_data)), 6841 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6842 .call = parse_vc_action_mplsoudp_encap, 6843 }, 6844 [ACTION_MPLSOUDP_DECAP] = { 6845 .name = "mplsoudp_decap", 6846 .help = "mplsoudp decapsulation, uses configuration set by" 6847 " \"set mplsoudp_decap\"", 6848 .priv = PRIV_ACTION(RAW_DECAP, 6849 sizeof(struct action_raw_decap_data)), 6850 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6851 .call = parse_vc_action_mplsoudp_decap, 6852 }, 6853 [ACTION_SET_IPV4_SRC] = { 6854 .name = "set_ipv4_src", 6855 .help = "Set a new IPv4 source address in the outermost" 6856 " IPv4 header", 6857 .priv = PRIV_ACTION(SET_IPV4_SRC, 6858 sizeof(struct rte_flow_action_set_ipv4)), 6859 .next = NEXT(action_set_ipv4_src), 6860 .call = parse_vc, 6861 }, 6862 [ACTION_SET_IPV4_SRC_IPV4_SRC] = { 6863 .name = "ipv4_addr", 6864 .help = "new IPv4 source address to set", 6865 .next = NEXT(action_set_ipv4_src, NEXT_ENTRY(COMMON_IPV4_ADDR)), 6866 .args = ARGS(ARGS_ENTRY_HTON 6867 (struct rte_flow_action_set_ipv4, ipv4_addr)), 6868 .call = parse_vc_conf, 6869 }, 6870 [ACTION_SET_IPV4_DST] = { 6871 .name = "set_ipv4_dst", 6872 .help = "Set a new IPv4 destination address in the outermost" 6873 " IPv4 header", 6874 .priv = PRIV_ACTION(SET_IPV4_DST, 6875 sizeof(struct rte_flow_action_set_ipv4)), 6876 .next = NEXT(action_set_ipv4_dst), 6877 .call = parse_vc, 6878 }, 6879 [ACTION_SET_IPV4_DST_IPV4_DST] = { 6880 .name = "ipv4_addr", 6881 .help = "new IPv4 destination address to set", 6882 .next = NEXT(action_set_ipv4_dst, NEXT_ENTRY(COMMON_IPV4_ADDR)), 6883 .args = ARGS(ARGS_ENTRY_HTON 6884 (struct rte_flow_action_set_ipv4, ipv4_addr)), 6885 .call = parse_vc_conf, 6886 }, 6887 [ACTION_SET_IPV6_SRC] = { 6888 .name = "set_ipv6_src", 6889 .help = "Set a new IPv6 source address in the outermost" 6890 " IPv6 header", 6891 .priv = PRIV_ACTION(SET_IPV6_SRC, 6892 sizeof(struct rte_flow_action_set_ipv6)), 6893 .next = NEXT(action_set_ipv6_src), 6894 .call = parse_vc, 6895 }, 6896 [ACTION_SET_IPV6_SRC_IPV6_SRC] = { 6897 .name = "ipv6_addr", 6898 .help = "new IPv6 source address to set", 6899 .next = NEXT(action_set_ipv6_src, NEXT_ENTRY(COMMON_IPV6_ADDR)), 6900 .args = ARGS(ARGS_ENTRY_HTON 6901 (struct rte_flow_action_set_ipv6, ipv6_addr)), 6902 .call = parse_vc_conf, 6903 }, 6904 [ACTION_SET_IPV6_DST] = { 6905 .name = "set_ipv6_dst", 6906 .help = "Set a new IPv6 destination address in the outermost" 6907 " IPv6 header", 6908 .priv = PRIV_ACTION(SET_IPV6_DST, 6909 sizeof(struct rte_flow_action_set_ipv6)), 6910 .next = NEXT(action_set_ipv6_dst), 6911 .call = parse_vc, 6912 }, 6913 [ACTION_SET_IPV6_DST_IPV6_DST] = { 6914 .name = "ipv6_addr", 6915 .help = "new IPv6 destination address to set", 6916 .next = NEXT(action_set_ipv6_dst, NEXT_ENTRY(COMMON_IPV6_ADDR)), 6917 .args = ARGS(ARGS_ENTRY_HTON 6918 (struct rte_flow_action_set_ipv6, ipv6_addr)), 6919 .call = parse_vc_conf, 6920 }, 6921 [ACTION_SET_TP_SRC] = { 6922 .name = "set_tp_src", 6923 .help = "set a new source port number in the outermost" 6924 " TCP/UDP header", 6925 .priv = PRIV_ACTION(SET_TP_SRC, 6926 sizeof(struct rte_flow_action_set_tp)), 6927 .next = NEXT(action_set_tp_src), 6928 .call = parse_vc, 6929 }, 6930 [ACTION_SET_TP_SRC_TP_SRC] = { 6931 .name = "port", 6932 .help = "new source port number to set", 6933 .next = NEXT(action_set_tp_src, NEXT_ENTRY(COMMON_UNSIGNED)), 6934 .args = ARGS(ARGS_ENTRY_HTON 6935 (struct rte_flow_action_set_tp, port)), 6936 .call = parse_vc_conf, 6937 }, 6938 [ACTION_SET_TP_DST] = { 6939 .name = "set_tp_dst", 6940 .help = "set a new destination port number in the outermost" 6941 " TCP/UDP header", 6942 .priv = PRIV_ACTION(SET_TP_DST, 6943 sizeof(struct rte_flow_action_set_tp)), 6944 .next = NEXT(action_set_tp_dst), 6945 .call = parse_vc, 6946 }, 6947 [ACTION_SET_TP_DST_TP_DST] = { 6948 .name = "port", 6949 .help = "new destination port number to set", 6950 .next = NEXT(action_set_tp_dst, NEXT_ENTRY(COMMON_UNSIGNED)), 6951 .args = ARGS(ARGS_ENTRY_HTON 6952 (struct rte_flow_action_set_tp, port)), 6953 .call = parse_vc_conf, 6954 }, 6955 [ACTION_MAC_SWAP] = { 6956 .name = "mac_swap", 6957 .help = "Swap the source and destination MAC addresses" 6958 " in the outermost Ethernet header", 6959 .priv = PRIV_ACTION(MAC_SWAP, 0), 6960 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6961 .call = parse_vc, 6962 }, 6963 [ACTION_DEC_TTL] = { 6964 .name = "dec_ttl", 6965 .help = "decrease network TTL if available", 6966 .priv = PRIV_ACTION(DEC_TTL, 0), 6967 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 6968 .call = parse_vc, 6969 }, 6970 [ACTION_SET_TTL] = { 6971 .name = "set_ttl", 6972 .help = "set ttl value", 6973 .priv = PRIV_ACTION(SET_TTL, 6974 sizeof(struct rte_flow_action_set_ttl)), 6975 .next = NEXT(action_set_ttl), 6976 .call = parse_vc, 6977 }, 6978 [ACTION_SET_TTL_TTL] = { 6979 .name = "ttl_value", 6980 .help = "new ttl value to set", 6981 .next = NEXT(action_set_ttl, NEXT_ENTRY(COMMON_UNSIGNED)), 6982 .args = ARGS(ARGS_ENTRY_HTON 6983 (struct rte_flow_action_set_ttl, ttl_value)), 6984 .call = parse_vc_conf, 6985 }, 6986 [ACTION_SET_MAC_SRC] = { 6987 .name = "set_mac_src", 6988 .help = "set source mac address", 6989 .priv = PRIV_ACTION(SET_MAC_SRC, 6990 sizeof(struct rte_flow_action_set_mac)), 6991 .next = NEXT(action_set_mac_src), 6992 .call = parse_vc, 6993 }, 6994 [ACTION_SET_MAC_SRC_MAC_SRC] = { 6995 .name = "mac_addr", 6996 .help = "new source mac address", 6997 .next = NEXT(action_set_mac_src, NEXT_ENTRY(COMMON_MAC_ADDR)), 6998 .args = ARGS(ARGS_ENTRY_HTON 6999 (struct rte_flow_action_set_mac, mac_addr)), 7000 .call = parse_vc_conf, 7001 }, 7002 [ACTION_SET_MAC_DST] = { 7003 .name = "set_mac_dst", 7004 .help = "set destination mac address", 7005 .priv = PRIV_ACTION(SET_MAC_DST, 7006 sizeof(struct rte_flow_action_set_mac)), 7007 .next = NEXT(action_set_mac_dst), 7008 .call = parse_vc, 7009 }, 7010 [ACTION_SET_MAC_DST_MAC_DST] = { 7011 .name = "mac_addr", 7012 .help = "new destination mac address to set", 7013 .next = NEXT(action_set_mac_dst, NEXT_ENTRY(COMMON_MAC_ADDR)), 7014 .args = ARGS(ARGS_ENTRY_HTON 7015 (struct rte_flow_action_set_mac, mac_addr)), 7016 .call = parse_vc_conf, 7017 }, 7018 [ACTION_INC_TCP_SEQ] = { 7019 .name = "inc_tcp_seq", 7020 .help = "increase TCP sequence number", 7021 .priv = PRIV_ACTION(INC_TCP_SEQ, sizeof(rte_be32_t)), 7022 .next = NEXT(action_inc_tcp_seq), 7023 .call = parse_vc, 7024 }, 7025 [ACTION_INC_TCP_SEQ_VALUE] = { 7026 .name = "value", 7027 .help = "the value to increase TCP sequence number by", 7028 .next = NEXT(action_inc_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)), 7029 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)), 7030 .call = parse_vc_conf, 7031 }, 7032 [ACTION_DEC_TCP_SEQ] = { 7033 .name = "dec_tcp_seq", 7034 .help = "decrease TCP sequence number", 7035 .priv = PRIV_ACTION(DEC_TCP_SEQ, sizeof(rte_be32_t)), 7036 .next = NEXT(action_dec_tcp_seq), 7037 .call = parse_vc, 7038 }, 7039 [ACTION_DEC_TCP_SEQ_VALUE] = { 7040 .name = "value", 7041 .help = "the value to decrease TCP sequence number by", 7042 .next = NEXT(action_dec_tcp_seq, NEXT_ENTRY(COMMON_UNSIGNED)), 7043 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)), 7044 .call = parse_vc_conf, 7045 }, 7046 [ACTION_INC_TCP_ACK] = { 7047 .name = "inc_tcp_ack", 7048 .help = "increase TCP acknowledgment number", 7049 .priv = PRIV_ACTION(INC_TCP_ACK, sizeof(rte_be32_t)), 7050 .next = NEXT(action_inc_tcp_ack), 7051 .call = parse_vc, 7052 }, 7053 [ACTION_INC_TCP_ACK_VALUE] = { 7054 .name = "value", 7055 .help = "the value to increase TCP acknowledgment number by", 7056 .next = NEXT(action_inc_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)), 7057 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)), 7058 .call = parse_vc_conf, 7059 }, 7060 [ACTION_DEC_TCP_ACK] = { 7061 .name = "dec_tcp_ack", 7062 .help = "decrease TCP acknowledgment number", 7063 .priv = PRIV_ACTION(DEC_TCP_ACK, sizeof(rte_be32_t)), 7064 .next = NEXT(action_dec_tcp_ack), 7065 .call = parse_vc, 7066 }, 7067 [ACTION_DEC_TCP_ACK_VALUE] = { 7068 .name = "value", 7069 .help = "the value to decrease TCP acknowledgment number by", 7070 .next = NEXT(action_dec_tcp_ack, NEXT_ENTRY(COMMON_UNSIGNED)), 7071 .args = ARGS(ARG_ENTRY_HTON(rte_be32_t)), 7072 .call = parse_vc_conf, 7073 }, 7074 [ACTION_RAW_ENCAP] = { 7075 .name = "raw_encap", 7076 .help = "encapsulation data, defined by set raw_encap", 7077 .priv = PRIV_ACTION(RAW_ENCAP, 7078 sizeof(struct action_raw_encap_data)), 7079 .next = NEXT(action_raw_encap), 7080 .call = parse_vc_action_raw_encap, 7081 }, 7082 [ACTION_RAW_ENCAP_SIZE] = { 7083 .name = "size", 7084 .help = "raw encap size", 7085 .next = NEXT(NEXT_ENTRY(ACTION_NEXT), 7086 NEXT_ENTRY(COMMON_UNSIGNED)), 7087 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_raw_encap, size)), 7088 .call = parse_vc_conf, 7089 }, 7090 [ACTION_RAW_ENCAP_INDEX] = { 7091 .name = "index", 7092 .help = "the index of raw_encap_confs", 7093 .next = NEXT(NEXT_ENTRY(ACTION_RAW_ENCAP_INDEX_VALUE)), 7094 }, 7095 [ACTION_RAW_ENCAP_INDEX_VALUE] = { 7096 .name = "{index}", 7097 .type = "UNSIGNED", 7098 .help = "unsigned integer value", 7099 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 7100 .call = parse_vc_action_raw_encap_index, 7101 .comp = comp_set_raw_index, 7102 }, 7103 [ACTION_RAW_DECAP] = { 7104 .name = "raw_decap", 7105 .help = "decapsulation data, defined by set raw_encap", 7106 .priv = PRIV_ACTION(RAW_DECAP, 7107 sizeof(struct action_raw_decap_data)), 7108 .next = NEXT(action_raw_decap), 7109 .call = parse_vc_action_raw_decap, 7110 }, 7111 [ACTION_RAW_DECAP_INDEX] = { 7112 .name = "index", 7113 .help = "the index of raw_encap_confs", 7114 .next = NEXT(NEXT_ENTRY(ACTION_RAW_DECAP_INDEX_VALUE)), 7115 }, 7116 [ACTION_RAW_DECAP_INDEX_VALUE] = { 7117 .name = "{index}", 7118 .type = "UNSIGNED", 7119 .help = "unsigned integer value", 7120 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 7121 .call = parse_vc_action_raw_decap_index, 7122 .comp = comp_set_raw_index, 7123 }, 7124 [ACTION_MODIFY_FIELD] = { 7125 .name = "modify_field", 7126 .help = "modify destination field with data from source field", 7127 .priv = PRIV_ACTION(MODIFY_FIELD, ACTION_MODIFY_SIZE), 7128 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_OP)), 7129 .call = parse_vc, 7130 }, 7131 [ACTION_MODIFY_FIELD_OP] = { 7132 .name = "op", 7133 .help = "operation type", 7134 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE), 7135 NEXT_ENTRY(ACTION_MODIFY_FIELD_OP_VALUE)), 7136 .call = parse_vc_conf, 7137 }, 7138 [ACTION_MODIFY_FIELD_OP_VALUE] = { 7139 .name = "{operation}", 7140 .help = "operation type value", 7141 .call = parse_vc_modify_field_op, 7142 .comp = comp_set_modify_field_op, 7143 }, 7144 [ACTION_MODIFY_FIELD_DST_TYPE] = { 7145 .name = "dst_type", 7146 .help = "destination field type", 7147 .next = NEXT(action_modify_field_dst, 7148 NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_TYPE_VALUE)), 7149 .call = parse_vc_conf, 7150 }, 7151 [ACTION_MODIFY_FIELD_DST_TYPE_VALUE] = { 7152 .name = "{dst_type}", 7153 .help = "destination field type value", 7154 .call = parse_vc_modify_field_id, 7155 .comp = comp_set_modify_field_id, 7156 }, 7157 [ACTION_MODIFY_FIELD_DST_LEVEL] = { 7158 .name = "dst_level", 7159 .help = "destination field level", 7160 .next = NEXT(action_modify_field_dst, 7161 NEXT_ENTRY(ACTION_MODIFY_FIELD_DST_LEVEL_VALUE)), 7162 .call = parse_vc_conf, 7163 }, 7164 [ACTION_MODIFY_FIELD_DST_LEVEL_VALUE] = { 7165 .name = "{dst_level}", 7166 .help = "destination field level value", 7167 .call = parse_vc_modify_field_level, 7168 .comp = comp_none, 7169 }, 7170 [ACTION_MODIFY_FIELD_DST_TAG_INDEX] = { 7171 .name = "dst_tag_index", 7172 .help = "destination field tag array", 7173 .next = NEXT(action_modify_field_dst, 7174 NEXT_ENTRY(COMMON_UNSIGNED)), 7175 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, 7176 dst.tag_index)), 7177 .call = parse_vc_conf, 7178 }, 7179 [ACTION_MODIFY_FIELD_DST_TYPE_ID] = { 7180 .name = "dst_type_id", 7181 .help = "destination field type ID", 7182 .next = NEXT(action_modify_field_dst, 7183 NEXT_ENTRY(COMMON_UNSIGNED)), 7184 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, 7185 dst.type)), 7186 .call = parse_vc_conf, 7187 }, 7188 [ACTION_MODIFY_FIELD_DST_CLASS_ID] = { 7189 .name = "dst_class", 7190 .help = "destination field class ID", 7191 .next = NEXT(action_modify_field_dst, 7192 NEXT_ENTRY(COMMON_UNSIGNED)), 7193 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field, 7194 dst.class_id)), 7195 .call = parse_vc_conf, 7196 }, 7197 [ACTION_MODIFY_FIELD_DST_OFFSET] = { 7198 .name = "dst_offset", 7199 .help = "destination field bit offset", 7200 .next = NEXT(action_modify_field_dst, 7201 NEXT_ENTRY(COMMON_UNSIGNED)), 7202 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, 7203 dst.offset)), 7204 .call = parse_vc_conf, 7205 }, 7206 [ACTION_MODIFY_FIELD_SRC_TYPE] = { 7207 .name = "src_type", 7208 .help = "source field type", 7209 .next = NEXT(action_modify_field_src, 7210 NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_TYPE_VALUE)), 7211 .call = parse_vc_conf, 7212 }, 7213 [ACTION_MODIFY_FIELD_SRC_TYPE_VALUE] = { 7214 .name = "{src_type}", 7215 .help = "source field type value", 7216 .call = parse_vc_modify_field_id, 7217 .comp = comp_set_modify_field_id, 7218 }, 7219 [ACTION_MODIFY_FIELD_SRC_LEVEL] = { 7220 .name = "src_level", 7221 .help = "source field level", 7222 .next = NEXT(action_modify_field_src, 7223 NEXT_ENTRY(ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE)), 7224 .call = parse_vc_conf, 7225 }, 7226 [ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE] = { 7227 .name = "{src_level}", 7228 .help = "source field level value", 7229 .call = parse_vc_modify_field_level, 7230 .comp = comp_none, 7231 }, 7232 [ACTION_MODIFY_FIELD_SRC_TAG_INDEX] = { 7233 .name = "stc_tag_index", 7234 .help = "source field tag array", 7235 .next = NEXT(action_modify_field_src, 7236 NEXT_ENTRY(COMMON_UNSIGNED)), 7237 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, 7238 src.tag_index)), 7239 .call = parse_vc_conf, 7240 }, 7241 [ACTION_MODIFY_FIELD_SRC_TYPE_ID] = { 7242 .name = "src_type_id", 7243 .help = "source field type ID", 7244 .next = NEXT(action_modify_field_src, 7245 NEXT_ENTRY(COMMON_UNSIGNED)), 7246 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, 7247 src.type)), 7248 .call = parse_vc_conf, 7249 }, 7250 [ACTION_MODIFY_FIELD_SRC_CLASS_ID] = { 7251 .name = "src_class", 7252 .help = "source field class ID", 7253 .next = NEXT(action_modify_field_src, 7254 NEXT_ENTRY(COMMON_UNSIGNED)), 7255 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_action_modify_field, 7256 src.class_id)), 7257 .call = parse_vc_conf, 7258 }, 7259 [ACTION_MODIFY_FIELD_SRC_OFFSET] = { 7260 .name = "src_offset", 7261 .help = "source field bit offset", 7262 .next = NEXT(action_modify_field_src, 7263 NEXT_ENTRY(COMMON_UNSIGNED)), 7264 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, 7265 src.offset)), 7266 .call = parse_vc_conf, 7267 }, 7268 [ACTION_MODIFY_FIELD_SRC_VALUE] = { 7269 .name = "src_value", 7270 .help = "source immediate value", 7271 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH), 7272 NEXT_ENTRY(COMMON_HEX)), 7273 .args = ARGS(ARGS_ENTRY_ARB(0, 0), 7274 ARGS_ENTRY_ARB(0, 0), 7275 ARGS_ENTRY(struct rte_flow_action_modify_field, 7276 src.value)), 7277 .call = parse_vc_conf, 7278 }, 7279 [ACTION_MODIFY_FIELD_SRC_POINTER] = { 7280 .name = "src_ptr", 7281 .help = "pointer to source immediate value", 7282 .next = NEXT(NEXT_ENTRY(ACTION_MODIFY_FIELD_WIDTH), 7283 NEXT_ENTRY(COMMON_HEX)), 7284 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, 7285 src.pvalue), 7286 ARGS_ENTRY_ARB(0, 0), 7287 ARGS_ENTRY_ARB 7288 (sizeof(struct rte_flow_action_modify_field), 7289 FLOW_FIELD_PATTERN_SIZE)), 7290 .call = parse_vc_conf, 7291 }, 7292 [ACTION_MODIFY_FIELD_WIDTH] = { 7293 .name = "width", 7294 .help = "number of bits to copy", 7295 .next = NEXT(NEXT_ENTRY(ACTION_NEXT), 7296 NEXT_ENTRY(COMMON_UNSIGNED)), 7297 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_modify_field, 7298 width)), 7299 .call = parse_vc_conf, 7300 }, 7301 [ACTION_SEND_TO_KERNEL] = { 7302 .name = "send_to_kernel", 7303 .help = "send packets to kernel", 7304 .priv = PRIV_ACTION(SEND_TO_KERNEL, 0), 7305 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 7306 .call = parse_vc, 7307 }, 7308 [ACTION_IPV6_EXT_REMOVE] = { 7309 .name = "ipv6_ext_remove", 7310 .help = "IPv6 extension type, defined by set ipv6_ext_remove", 7311 .priv = PRIV_ACTION(IPV6_EXT_REMOVE, 7312 sizeof(struct action_ipv6_ext_remove_data)), 7313 .next = NEXT(action_ipv6_ext_remove), 7314 .call = parse_vc_action_ipv6_ext_remove, 7315 }, 7316 [ACTION_IPV6_EXT_REMOVE_INDEX] = { 7317 .name = "index", 7318 .help = "the index of ipv6_ext_remove", 7319 .next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_REMOVE_INDEX_VALUE)), 7320 }, 7321 [ACTION_IPV6_EXT_REMOVE_INDEX_VALUE] = { 7322 .name = "{index}", 7323 .type = "UNSIGNED", 7324 .help = "unsigned integer value", 7325 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 7326 .call = parse_vc_action_ipv6_ext_remove_index, 7327 .comp = comp_set_ipv6_ext_index, 7328 }, 7329 [ACTION_IPV6_EXT_PUSH] = { 7330 .name = "ipv6_ext_push", 7331 .help = "IPv6 extension data, defined by set ipv6_ext_push", 7332 .priv = PRIV_ACTION(IPV6_EXT_PUSH, 7333 sizeof(struct action_ipv6_ext_push_data)), 7334 .next = NEXT(action_ipv6_ext_push), 7335 .call = parse_vc_action_ipv6_ext_push, 7336 }, 7337 [ACTION_IPV6_EXT_PUSH_INDEX] = { 7338 .name = "index", 7339 .help = "the index of ipv6_ext_push", 7340 .next = NEXT(NEXT_ENTRY(ACTION_IPV6_EXT_PUSH_INDEX_VALUE)), 7341 }, 7342 [ACTION_IPV6_EXT_PUSH_INDEX_VALUE] = { 7343 .name = "{index}", 7344 .type = "UNSIGNED", 7345 .help = "unsigned integer value", 7346 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 7347 .call = parse_vc_action_ipv6_ext_push_index, 7348 .comp = comp_set_ipv6_ext_index, 7349 }, 7350 [ACTION_NAT64] = { 7351 .name = "nat64", 7352 .help = "NAT64 IP headers translation", 7353 .priv = PRIV_ACTION(NAT64, sizeof(struct rte_flow_action_nat64)), 7354 .next = NEXT(action_nat64), 7355 .call = parse_vc, 7356 }, 7357 [ACTION_NAT64_MODE] = { 7358 .name = "type", 7359 .help = "NAT64 translation type", 7360 .next = NEXT(action_nat64, NEXT_ENTRY(COMMON_UNSIGNED)), 7361 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_nat64, type)), 7362 .call = parse_vc_conf, 7363 }, 7364 /* Top level command. */ 7365 [SET] = { 7366 .name = "set", 7367 .help = "set raw encap/decap/sample data", 7368 .type = "set raw_encap|raw_decap <index> <pattern>" 7369 " or set sample_actions <index> <action>", 7370 .next = NEXT(NEXT_ENTRY 7371 (SET_RAW_ENCAP, 7372 SET_RAW_DECAP, 7373 SET_SAMPLE_ACTIONS, 7374 SET_IPV6_EXT_REMOVE, 7375 SET_IPV6_EXT_PUSH)), 7376 .call = parse_set_init, 7377 }, 7378 /* Sub-level commands. */ 7379 [SET_RAW_ENCAP] = { 7380 .name = "raw_encap", 7381 .help = "set raw encap data", 7382 .next = NEXT(next_set_raw), 7383 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED 7384 (offsetof(struct buffer, port), 7385 sizeof(((struct buffer *)0)->port), 7386 0, RAW_ENCAP_CONFS_MAX_NUM - 1)), 7387 .call = parse_set_raw_encap_decap, 7388 }, 7389 [SET_RAW_DECAP] = { 7390 .name = "raw_decap", 7391 .help = "set raw decap data", 7392 .next = NEXT(next_set_raw), 7393 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED 7394 (offsetof(struct buffer, port), 7395 sizeof(((struct buffer *)0)->port), 7396 0, RAW_ENCAP_CONFS_MAX_NUM - 1)), 7397 .call = parse_set_raw_encap_decap, 7398 }, 7399 [SET_RAW_INDEX] = { 7400 .name = "{index}", 7401 .type = "COMMON_UNSIGNED", 7402 .help = "index of raw_encap/raw_decap data", 7403 .next = NEXT(next_item), 7404 .call = parse_port, 7405 }, 7406 [SET_SAMPLE_INDEX] = { 7407 .name = "{index}", 7408 .type = "UNSIGNED", 7409 .help = "index of sample actions", 7410 .next = NEXT(next_action_sample), 7411 .call = parse_port, 7412 }, 7413 [SET_SAMPLE_ACTIONS] = { 7414 .name = "sample_actions", 7415 .help = "set sample actions list", 7416 .next = NEXT(NEXT_ENTRY(SET_SAMPLE_INDEX)), 7417 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED 7418 (offsetof(struct buffer, port), 7419 sizeof(((struct buffer *)0)->port), 7420 0, RAW_SAMPLE_CONFS_MAX_NUM - 1)), 7421 .call = parse_set_sample_action, 7422 }, 7423 [SET_IPV6_EXT_PUSH] = { 7424 .name = "ipv6_ext_push", 7425 .help = "set IPv6 extension header", 7426 .next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)), 7427 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED 7428 (offsetof(struct buffer, port), 7429 sizeof(((struct buffer *)0)->port), 7430 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)), 7431 .call = parse_set_ipv6_ext_action, 7432 }, 7433 [SET_IPV6_EXT_REMOVE] = { 7434 .name = "ipv6_ext_remove", 7435 .help = "set IPv6 extension header", 7436 .next = NEXT(NEXT_ENTRY(SET_IPV6_EXT_INDEX)), 7437 .args = ARGS(ARGS_ENTRY_ARB_BOUNDED 7438 (offsetof(struct buffer, port), 7439 sizeof(((struct buffer *)0)->port), 7440 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1)), 7441 .call = parse_set_ipv6_ext_action, 7442 }, 7443 [SET_IPV6_EXT_INDEX] = { 7444 .name = "{index}", 7445 .type = "UNSIGNED", 7446 .help = "index of ipv6 extension push/remove actions", 7447 .next = NEXT(item_ipv6_push_ext), 7448 .call = parse_port, 7449 }, 7450 [ITEM_IPV6_PUSH_REMOVE_EXT] = { 7451 .name = "ipv6_ext", 7452 .help = "set IPv6 extension header", 7453 .priv = PRIV_ITEM(IPV6_EXT, 7454 sizeof(struct rte_flow_item_ipv6_ext)), 7455 .next = NEXT(item_ipv6_push_ext_type), 7456 .call = parse_vc, 7457 }, 7458 [ITEM_IPV6_PUSH_REMOVE_EXT_TYPE] = { 7459 .name = "type", 7460 .help = "set IPv6 extension type", 7461 .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext, 7462 next_hdr)), 7463 .next = NEXT(item_ipv6_push_ext_header, NEXT_ENTRY(COMMON_UNSIGNED), 7464 item_param), 7465 }, 7466 [ACTION_SET_TAG] = { 7467 .name = "set_tag", 7468 .help = "set tag", 7469 .priv = PRIV_ACTION(SET_TAG, 7470 sizeof(struct rte_flow_action_set_tag)), 7471 .next = NEXT(action_set_tag), 7472 .call = parse_vc, 7473 }, 7474 [ACTION_SET_TAG_INDEX] = { 7475 .name = "index", 7476 .help = "index of tag array", 7477 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)), 7478 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_set_tag, index)), 7479 .call = parse_vc_conf, 7480 }, 7481 [ACTION_SET_TAG_DATA] = { 7482 .name = "data", 7483 .help = "tag value", 7484 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)), 7485 .args = ARGS(ARGS_ENTRY 7486 (struct rte_flow_action_set_tag, data)), 7487 .call = parse_vc_conf, 7488 }, 7489 [ACTION_SET_TAG_MASK] = { 7490 .name = "mask", 7491 .help = "mask for tag value", 7492 .next = NEXT(action_set_tag, NEXT_ENTRY(COMMON_UNSIGNED)), 7493 .args = ARGS(ARGS_ENTRY 7494 (struct rte_flow_action_set_tag, mask)), 7495 .call = parse_vc_conf, 7496 }, 7497 [ACTION_SET_META] = { 7498 .name = "set_meta", 7499 .help = "set metadata", 7500 .priv = PRIV_ACTION(SET_META, 7501 sizeof(struct rte_flow_action_set_meta)), 7502 .next = NEXT(action_set_meta), 7503 .call = parse_vc_action_set_meta, 7504 }, 7505 [ACTION_SET_META_DATA] = { 7506 .name = "data", 7507 .help = "metadata value", 7508 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)), 7509 .args = ARGS(ARGS_ENTRY 7510 (struct rte_flow_action_set_meta, data)), 7511 .call = parse_vc_conf, 7512 }, 7513 [ACTION_SET_META_MASK] = { 7514 .name = "mask", 7515 .help = "mask for metadata value", 7516 .next = NEXT(action_set_meta, NEXT_ENTRY(COMMON_UNSIGNED)), 7517 .args = ARGS(ARGS_ENTRY 7518 (struct rte_flow_action_set_meta, mask)), 7519 .call = parse_vc_conf, 7520 }, 7521 [ACTION_SET_IPV4_DSCP] = { 7522 .name = "set_ipv4_dscp", 7523 .help = "set DSCP value", 7524 .priv = PRIV_ACTION(SET_IPV4_DSCP, 7525 sizeof(struct rte_flow_action_set_dscp)), 7526 .next = NEXT(action_set_ipv4_dscp), 7527 .call = parse_vc, 7528 }, 7529 [ACTION_SET_IPV4_DSCP_VALUE] = { 7530 .name = "dscp_value", 7531 .help = "new IPv4 DSCP value to set", 7532 .next = NEXT(action_set_ipv4_dscp, NEXT_ENTRY(COMMON_UNSIGNED)), 7533 .args = ARGS(ARGS_ENTRY 7534 (struct rte_flow_action_set_dscp, dscp)), 7535 .call = parse_vc_conf, 7536 }, 7537 [ACTION_SET_IPV6_DSCP] = { 7538 .name = "set_ipv6_dscp", 7539 .help = "set DSCP value", 7540 .priv = PRIV_ACTION(SET_IPV6_DSCP, 7541 sizeof(struct rte_flow_action_set_dscp)), 7542 .next = NEXT(action_set_ipv6_dscp), 7543 .call = parse_vc, 7544 }, 7545 [ACTION_SET_IPV6_DSCP_VALUE] = { 7546 .name = "dscp_value", 7547 .help = "new IPv6 DSCP value to set", 7548 .next = NEXT(action_set_ipv6_dscp, NEXT_ENTRY(COMMON_UNSIGNED)), 7549 .args = ARGS(ARGS_ENTRY 7550 (struct rte_flow_action_set_dscp, dscp)), 7551 .call = parse_vc_conf, 7552 }, 7553 [ACTION_AGE] = { 7554 .name = "age", 7555 .help = "set a specific metadata header", 7556 .next = NEXT(action_age), 7557 .priv = PRIV_ACTION(AGE, 7558 sizeof(struct rte_flow_action_age)), 7559 .call = parse_vc, 7560 }, 7561 [ACTION_AGE_TIMEOUT] = { 7562 .name = "timeout", 7563 .help = "flow age timeout value", 7564 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_action_age, 7565 timeout, 24)), 7566 .next = NEXT(action_age, NEXT_ENTRY(COMMON_UNSIGNED)), 7567 .call = parse_vc_conf, 7568 }, 7569 [ACTION_AGE_UPDATE] = { 7570 .name = "age_update", 7571 .help = "update aging parameter", 7572 .next = NEXT(action_age_update), 7573 .priv = PRIV_ACTION(AGE, 7574 sizeof(struct rte_flow_update_age)), 7575 .call = parse_vc, 7576 }, 7577 [ACTION_AGE_UPDATE_TIMEOUT] = { 7578 .name = "timeout", 7579 .help = "age timeout update value", 7580 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age, 7581 timeout, 24)), 7582 .next = NEXT(action_age_update, NEXT_ENTRY(COMMON_UNSIGNED)), 7583 .call = parse_vc_conf_timeout, 7584 }, 7585 [ACTION_AGE_UPDATE_TOUCH] = { 7586 .name = "touch", 7587 .help = "this flow is touched", 7588 .next = NEXT(action_age_update, NEXT_ENTRY(COMMON_BOOLEAN)), 7589 .args = ARGS(ARGS_ENTRY_BF(struct rte_flow_update_age, 7590 touch, 1)), 7591 .call = parse_vc_conf, 7592 }, 7593 [ACTION_SAMPLE] = { 7594 .name = "sample", 7595 .help = "set a sample action", 7596 .next = NEXT(action_sample), 7597 .priv = PRIV_ACTION(SAMPLE, 7598 sizeof(struct action_sample_data)), 7599 .call = parse_vc_action_sample, 7600 }, 7601 [ACTION_SAMPLE_RATIO] = { 7602 .name = "ratio", 7603 .help = "flow sample ratio value", 7604 .next = NEXT(action_sample, NEXT_ENTRY(COMMON_UNSIGNED)), 7605 .args = ARGS(ARGS_ENTRY_ARB 7606 (offsetof(struct action_sample_data, conf) + 7607 offsetof(struct rte_flow_action_sample, ratio), 7608 sizeof(((struct rte_flow_action_sample *)0)-> 7609 ratio))), 7610 }, 7611 [ACTION_SAMPLE_INDEX] = { 7612 .name = "index", 7613 .help = "the index of sample actions list", 7614 .next = NEXT(NEXT_ENTRY(ACTION_SAMPLE_INDEX_VALUE)), 7615 }, 7616 [ACTION_SAMPLE_INDEX_VALUE] = { 7617 .name = "{index}", 7618 .type = "COMMON_UNSIGNED", 7619 .help = "unsigned integer value", 7620 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 7621 .call = parse_vc_action_sample_index, 7622 .comp = comp_set_sample_index, 7623 }, 7624 [ACTION_CONNTRACK] = { 7625 .name = "conntrack", 7626 .help = "create a conntrack object", 7627 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 7628 .priv = PRIV_ACTION(CONNTRACK, 7629 sizeof(struct rte_flow_action_conntrack)), 7630 .call = parse_vc, 7631 }, 7632 [ACTION_CONNTRACK_UPDATE] = { 7633 .name = "conntrack_update", 7634 .help = "update a conntrack object", 7635 .next = NEXT(action_update_conntrack), 7636 .priv = PRIV_ACTION(CONNTRACK, 7637 sizeof(struct rte_flow_modify_conntrack)), 7638 .call = parse_vc, 7639 }, 7640 [ACTION_CONNTRACK_UPDATE_DIR] = { 7641 .name = "dir", 7642 .help = "update a conntrack object direction", 7643 .next = NEXT(action_update_conntrack), 7644 .call = parse_vc_action_conntrack_update, 7645 }, 7646 [ACTION_CONNTRACK_UPDATE_CTX] = { 7647 .name = "ctx", 7648 .help = "update a conntrack object context", 7649 .next = NEXT(action_update_conntrack), 7650 .call = parse_vc_action_conntrack_update, 7651 }, 7652 [ACTION_PORT_REPRESENTOR] = { 7653 .name = "port_representor", 7654 .help = "at embedded switch level, send matching traffic to the given ethdev", 7655 .priv = PRIV_ACTION(PORT_REPRESENTOR, 7656 sizeof(struct rte_flow_action_ethdev)), 7657 .next = NEXT(action_port_representor), 7658 .call = parse_vc, 7659 }, 7660 [ACTION_PORT_REPRESENTOR_PORT_ID] = { 7661 .name = "port_id", 7662 .help = "ethdev port ID", 7663 .next = NEXT(action_port_representor, 7664 NEXT_ENTRY(COMMON_UNSIGNED)), 7665 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev, 7666 port_id)), 7667 .call = parse_vc_conf, 7668 }, 7669 [ACTION_REPRESENTED_PORT] = { 7670 .name = "represented_port", 7671 .help = "at embedded switch level, send matching traffic to the entity represented by the given ethdev", 7672 .priv = PRIV_ACTION(REPRESENTED_PORT, 7673 sizeof(struct rte_flow_action_ethdev)), 7674 .next = NEXT(action_represented_port), 7675 .call = parse_vc, 7676 }, 7677 [ACTION_REPRESENTED_PORT_ETHDEV_PORT_ID] = { 7678 .name = "ethdev_port_id", 7679 .help = "ethdev port ID", 7680 .next = NEXT(action_represented_port, 7681 NEXT_ENTRY(COMMON_UNSIGNED)), 7682 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_ethdev, 7683 port_id)), 7684 .call = parse_vc_conf, 7685 }, 7686 /* Indirect action destroy arguments. */ 7687 [INDIRECT_ACTION_DESTROY_ID] = { 7688 .name = "action_id", 7689 .help = "specify a indirect action id to destroy", 7690 .next = NEXT(next_ia_destroy_attr, 7691 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), 7692 .args = ARGS(ARGS_ENTRY_PTR(struct buffer, 7693 args.ia_destroy.action_id)), 7694 .call = parse_ia_destroy, 7695 }, 7696 /* Indirect action create arguments. */ 7697 [INDIRECT_ACTION_CREATE_ID] = { 7698 .name = "action_id", 7699 .help = "specify a indirect action id to create", 7700 .next = NEXT(next_ia_create_attr, 7701 NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)), 7702 .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)), 7703 }, 7704 [ACTION_INDIRECT] = { 7705 .name = "indirect", 7706 .help = "apply indirect action by id", 7707 .priv = PRIV_ACTION(INDIRECT, 0), 7708 .next = NEXT(next_ia), 7709 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))), 7710 .call = parse_vc, 7711 }, 7712 [ACTION_INDIRECT_LIST] = { 7713 .name = "indirect_list", 7714 .help = "apply indirect list action by id", 7715 .priv = PRIV_ACTION(INDIRECT_LIST, 7716 sizeof(struct 7717 rte_flow_action_indirect_list)), 7718 .next = NEXT(next_ial), 7719 .call = parse_vc, 7720 }, 7721 [ACTION_INDIRECT_LIST_HANDLE] = { 7722 .name = "handle", 7723 .help = "indirect list handle", 7724 .next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_HANDLE)), 7725 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))), 7726 }, 7727 [ACTION_INDIRECT_LIST_CONF] = { 7728 .name = "conf", 7729 .help = "indirect list configuration", 7730 .next = NEXT(next_ial, NEXT_ENTRY(INDIRECT_LIST_ACTION_ID2PTR_CONF)), 7731 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))), 7732 }, 7733 [INDIRECT_LIST_ACTION_ID2PTR_HANDLE] = { 7734 .type = "UNSIGNED", 7735 .help = "unsigned integer value", 7736 .call = parse_indlst_id2ptr, 7737 }, 7738 [INDIRECT_LIST_ACTION_ID2PTR_CONF] = { 7739 .type = "UNSIGNED", 7740 .help = "unsigned integer value", 7741 .call = parse_indlst_id2ptr, 7742 }, 7743 [ACTION_SHARED_INDIRECT] = { 7744 .name = "shared_indirect", 7745 .help = "apply indirect action by id and port", 7746 .priv = PRIV_ACTION(INDIRECT, 0), 7747 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_PORT)), 7748 .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t)), 7749 ARGS_ENTRY_ARB(0, sizeof(uint32_t))), 7750 .call = parse_vc, 7751 }, 7752 [INDIRECT_ACTION_PORT] = { 7753 .name = "{indirect_action_port}", 7754 .type = "INDIRECT_ACTION_PORT", 7755 .help = "indirect action port", 7756 .next = NEXT(NEXT_ENTRY(INDIRECT_ACTION_ID2PTR)), 7757 .call = parse_ia_port, 7758 .comp = comp_none, 7759 }, 7760 [INDIRECT_ACTION_ID2PTR] = { 7761 .name = "{action_id}", 7762 .type = "INDIRECT_ACTION_ID", 7763 .help = "indirect action id", 7764 .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), 7765 .call = parse_ia_id2ptr, 7766 .comp = comp_none, 7767 }, 7768 [INDIRECT_ACTION_INGRESS] = { 7769 .name = "ingress", 7770 .help = "affect rule to ingress", 7771 .next = NEXT(next_ia_create_attr), 7772 .call = parse_ia, 7773 }, 7774 [INDIRECT_ACTION_EGRESS] = { 7775 .name = "egress", 7776 .help = "affect rule to egress", 7777 .next = NEXT(next_ia_create_attr), 7778 .call = parse_ia, 7779 }, 7780 [INDIRECT_ACTION_TRANSFER] = { 7781 .name = "transfer", 7782 .help = "affect rule to transfer", 7783 .next = NEXT(next_ia_create_attr), 7784 .call = parse_ia, 7785 }, 7786 [INDIRECT_ACTION_SPEC] = { 7787 .name = "action", 7788 .help = "specify action to create indirect handle", 7789 .next = NEXT(next_action), 7790 }, 7791 [INDIRECT_ACTION_LIST] = { 7792 .name = "list", 7793 .help = "specify actions for indirect handle list", 7794 .next = NEXT(NEXT_ENTRY(ACTIONS, END)), 7795 .call = parse_ia, 7796 }, 7797 [INDIRECT_ACTION_FLOW_CONF] = { 7798 .name = "flow_conf", 7799 .help = "specify actions configuration for indirect handle list", 7800 .next = NEXT(NEXT_ENTRY(ACTIONS, END)), 7801 .call = parse_ia, 7802 }, 7803 [ACTION_POL_G] = { 7804 .name = "g_actions", 7805 .help = "submit a list of associated actions for green", 7806 .next = NEXT(next_action), 7807 .call = parse_mp, 7808 }, 7809 [ACTION_POL_Y] = { 7810 .name = "y_actions", 7811 .help = "submit a list of associated actions for yellow", 7812 .next = NEXT(next_action), 7813 }, 7814 [ACTION_POL_R] = { 7815 .name = "r_actions", 7816 .help = "submit a list of associated actions for red", 7817 .next = NEXT(next_action), 7818 }, 7819 [ACTION_QUOTA_CREATE] = { 7820 .name = "quota_create", 7821 .help = "create quota action", 7822 .priv = PRIV_ACTION(QUOTA, 7823 sizeof(struct rte_flow_action_quota)), 7824 .next = NEXT(action_quota_create), 7825 .call = parse_vc 7826 }, 7827 [ACTION_QUOTA_CREATE_LIMIT] = { 7828 .name = "limit", 7829 .help = "quota limit", 7830 .next = NEXT(action_quota_create, NEXT_ENTRY(COMMON_UNSIGNED)), 7831 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, quota)), 7832 .call = parse_vc_conf 7833 }, 7834 [ACTION_QUOTA_CREATE_MODE] = { 7835 .name = "mode", 7836 .help = "quota mode", 7837 .next = NEXT(action_quota_create, 7838 NEXT_ENTRY(ACTION_QUOTA_CREATE_MODE_NAME)), 7839 .args = ARGS(ARGS_ENTRY(struct rte_flow_action_quota, mode)), 7840 .call = parse_vc_conf 7841 }, 7842 [ACTION_QUOTA_CREATE_MODE_NAME] = { 7843 .name = "mode_name", 7844 .help = "quota mode name", 7845 .call = parse_quota_mode_name, 7846 .comp = comp_quota_mode_name 7847 }, 7848 [ACTION_QUOTA_QU] = { 7849 .name = "quota_update", 7850 .help = "update quota action", 7851 .priv = PRIV_ACTION(QUOTA, 7852 sizeof(struct rte_flow_update_quota)), 7853 .next = NEXT(action_quota_update), 7854 .call = parse_vc 7855 }, 7856 [ACTION_QUOTA_QU_LIMIT] = { 7857 .name = "limit", 7858 .help = "quota limit", 7859 .next = NEXT(action_quota_update, NEXT_ENTRY(COMMON_UNSIGNED)), 7860 .args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, quota)), 7861 .call = parse_vc_conf 7862 }, 7863 [ACTION_QUOTA_QU_UPDATE_OP] = { 7864 .name = "update_op", 7865 .help = "query update op SET|ADD", 7866 .next = NEXT(action_quota_update, 7867 NEXT_ENTRY(ACTION_QUOTA_QU_UPDATE_OP_NAME)), 7868 .args = ARGS(ARGS_ENTRY(struct rte_flow_update_quota, op)), 7869 .call = parse_vc_conf 7870 }, 7871 [ACTION_QUOTA_QU_UPDATE_OP_NAME] = { 7872 .name = "update_op_name", 7873 .help = "quota update op name", 7874 .call = parse_quota_update_name, 7875 .comp = comp_quota_update_name 7876 }, 7877 7878 /* Top-level command. */ 7879 [ADD] = { 7880 .name = "add", 7881 .type = "port meter policy {port_id} {arg}", 7882 .help = "add port meter policy", 7883 .next = NEXT(NEXT_ENTRY(ITEM_POL_PORT)), 7884 .call = parse_init, 7885 }, 7886 /* Sub-level commands. */ 7887 [ITEM_POL_PORT] = { 7888 .name = "port", 7889 .help = "add port meter policy", 7890 .next = NEXT(NEXT_ENTRY(ITEM_POL_METER)), 7891 }, 7892 [ITEM_POL_METER] = { 7893 .name = "meter", 7894 .help = "add port meter policy", 7895 .next = NEXT(NEXT_ENTRY(ITEM_POL_POLICY)), 7896 }, 7897 [ITEM_POL_POLICY] = { 7898 .name = "policy", 7899 .help = "add port meter policy", 7900 .next = NEXT(NEXT_ENTRY(ACTION_POL_R), 7901 NEXT_ENTRY(ACTION_POL_Y), 7902 NEXT_ENTRY(ACTION_POL_G), 7903 NEXT_ENTRY(COMMON_POLICY_ID), 7904 NEXT_ENTRY(COMMON_PORT_ID)), 7905 .args = ARGS(ARGS_ENTRY(struct buffer, args.policy.policy_id), 7906 ARGS_ENTRY(struct buffer, port)), 7907 .call = parse_mp, 7908 }, 7909 [ITEM_AGGR_AFFINITY] = { 7910 .name = "aggr_affinity", 7911 .help = "match on the aggregated port receiving the packets", 7912 .priv = PRIV_ITEM(AGGR_AFFINITY, 7913 sizeof(struct rte_flow_item_aggr_affinity)), 7914 .next = NEXT(item_aggr_affinity), 7915 .call = parse_vc, 7916 }, 7917 [ITEM_AGGR_AFFINITY_VALUE] = { 7918 .name = "affinity", 7919 .help = "aggregated affinity value", 7920 .next = NEXT(item_aggr_affinity, NEXT_ENTRY(COMMON_UNSIGNED), 7921 item_param), 7922 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_aggr_affinity, 7923 affinity)), 7924 }, 7925 [ITEM_TX_QUEUE] = { 7926 .name = "tx_queue", 7927 .help = "match on the tx queue of send packet", 7928 .priv = PRIV_ITEM(TX_QUEUE, 7929 sizeof(struct rte_flow_item_tx_queue)), 7930 .next = NEXT(item_tx_queue), 7931 .call = parse_vc, 7932 }, 7933 [ITEM_TX_QUEUE_VALUE] = { 7934 .name = "tx_queue_value", 7935 .help = "tx queue value", 7936 .next = NEXT(item_tx_queue, NEXT_ENTRY(COMMON_UNSIGNED), 7937 item_param), 7938 .args = ARGS(ARGS_ENTRY(struct rte_flow_item_tx_queue, 7939 tx_queue)), 7940 }, 7941 }; 7942 7943 /** Remove and return last entry from argument stack. */ 7944 static const struct arg * 7945 pop_args(struct context *ctx) 7946 { 7947 return ctx->args_num ? ctx->args[--ctx->args_num] : NULL; 7948 } 7949 7950 /** Add entry on top of the argument stack. */ 7951 static int 7952 push_args(struct context *ctx, const struct arg *arg) 7953 { 7954 if (ctx->args_num == CTX_STACK_SIZE) 7955 return -1; 7956 ctx->args[ctx->args_num++] = arg; 7957 return 0; 7958 } 7959 7960 /** Spread value into buffer according to bit-mask. */ 7961 static size_t 7962 arg_entry_bf_fill(void *dst, uintmax_t val, const struct arg *arg) 7963 { 7964 uint32_t i = arg->size; 7965 uint32_t end = 0; 7966 int sub = 1; 7967 int add = 0; 7968 size_t len = 0; 7969 7970 if (!arg->mask) 7971 return 0; 7972 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 7973 if (!arg->hton) { 7974 i = 0; 7975 end = arg->size; 7976 sub = 0; 7977 add = 1; 7978 } 7979 #endif 7980 while (i != end) { 7981 unsigned int shift = 0; 7982 uint8_t *buf = (uint8_t *)dst + arg->offset + (i -= sub); 7983 7984 for (shift = 0; arg->mask[i] >> shift; ++shift) { 7985 if (!(arg->mask[i] & (1 << shift))) 7986 continue; 7987 ++len; 7988 if (!dst) 7989 continue; 7990 *buf &= ~(1 << shift); 7991 *buf |= (val & 1) << shift; 7992 val >>= 1; 7993 } 7994 i += add; 7995 } 7996 return len; 7997 } 7998 7999 /** Compare a string with a partial one of a given length. */ 8000 static int 8001 strcmp_partial(const char *full, const char *partial, size_t partial_len) 8002 { 8003 int r = strncmp(full, partial, partial_len); 8004 8005 if (r) 8006 return r; 8007 if (strlen(full) <= partial_len) 8008 return 0; 8009 return full[partial_len]; 8010 } 8011 8012 /** 8013 * Parse a prefix length and generate a bit-mask. 8014 * 8015 * Last argument (ctx->args) is retrieved to determine mask size, storage 8016 * location and whether the result must use network byte ordering. 8017 */ 8018 static int 8019 parse_prefix(struct context *ctx, const struct token *token, 8020 const char *str, unsigned int len, 8021 void *buf, unsigned int size) 8022 { 8023 const struct arg *arg = pop_args(ctx); 8024 static const uint8_t conv[] = "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff"; 8025 char *end; 8026 uintmax_t u; 8027 unsigned int bytes; 8028 unsigned int extra; 8029 8030 (void)token; 8031 /* Argument is expected. */ 8032 if (!arg) 8033 return -1; 8034 errno = 0; 8035 u = strtoumax(str, &end, 0); 8036 if (errno || (size_t)(end - str) != len) 8037 goto error; 8038 if (arg->mask) { 8039 uintmax_t v = 0; 8040 8041 extra = arg_entry_bf_fill(NULL, 0, arg); 8042 if (u > extra) 8043 goto error; 8044 if (!ctx->object) 8045 return len; 8046 extra -= u; 8047 while (u--) 8048 (v <<= 1, v |= 1); 8049 v <<= extra; 8050 if (!arg_entry_bf_fill(ctx->object, v, arg) || 8051 !arg_entry_bf_fill(ctx->objmask, -1, arg)) 8052 goto error; 8053 return len; 8054 } 8055 bytes = u / 8; 8056 extra = u % 8; 8057 size = arg->size; 8058 if (bytes > size || bytes + !!extra > size) 8059 goto error; 8060 if (!ctx->object) 8061 return len; 8062 buf = (uint8_t *)ctx->object + arg->offset; 8063 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 8064 if (!arg->hton) { 8065 memset((uint8_t *)buf + size - bytes, 0xff, bytes); 8066 memset(buf, 0x00, size - bytes); 8067 if (extra) 8068 ((uint8_t *)buf)[size - bytes - 1] = conv[extra]; 8069 } else 8070 #endif 8071 { 8072 memset(buf, 0xff, bytes); 8073 memset((uint8_t *)buf + bytes, 0x00, size - bytes); 8074 if (extra) 8075 ((uint8_t *)buf)[bytes] = conv[extra]; 8076 } 8077 if (ctx->objmask) 8078 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 8079 return len; 8080 error: 8081 push_args(ctx, arg); 8082 return -1; 8083 } 8084 8085 /** Default parsing function for token name matching. */ 8086 static int 8087 parse_default(struct context *ctx, const struct token *token, 8088 const char *str, unsigned int len, 8089 void *buf, unsigned int size) 8090 { 8091 (void)ctx; 8092 (void)buf; 8093 (void)size; 8094 if (strcmp_partial(token->name, str, len)) 8095 return -1; 8096 return len; 8097 } 8098 8099 /** Parse flow command, initialize output buffer for subsequent tokens. */ 8100 static int 8101 parse_init(struct context *ctx, const struct token *token, 8102 const char *str, unsigned int len, 8103 void *buf, unsigned int size) 8104 { 8105 struct buffer *out = buf; 8106 8107 /* Token name must match. */ 8108 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8109 return -1; 8110 /* Nothing else to do if there is no buffer. */ 8111 if (!out) 8112 return len; 8113 /* Make sure buffer is large enough. */ 8114 if (size < sizeof(*out)) 8115 return -1; 8116 /* Initialize buffer. */ 8117 memset(out, 0x00, sizeof(*out)); 8118 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out)); 8119 ctx->objdata = 0; 8120 ctx->object = out; 8121 ctx->objmask = NULL; 8122 return len; 8123 } 8124 8125 /** Parse tokens for indirect action commands. */ 8126 static int 8127 parse_ia(struct context *ctx, const struct token *token, 8128 const char *str, unsigned int len, 8129 void *buf, unsigned int size) 8130 { 8131 struct buffer *out = buf; 8132 8133 /* Token name must match. */ 8134 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8135 return -1; 8136 /* Nothing else to do if there is no buffer. */ 8137 if (!out) 8138 return len; 8139 if (!out->command) { 8140 if (ctx->curr != INDIRECT_ACTION) 8141 return -1; 8142 if (sizeof(*out) > size) 8143 return -1; 8144 out->command = ctx->curr; 8145 ctx->objdata = 0; 8146 ctx->object = out; 8147 ctx->objmask = NULL; 8148 out->args.vc.data = (uint8_t *)out + size; 8149 return len; 8150 } 8151 switch (ctx->curr) { 8152 case INDIRECT_ACTION_CREATE: 8153 case INDIRECT_ACTION_UPDATE: 8154 case INDIRECT_ACTION_QUERY_UPDATE: 8155 out->args.vc.actions = 8156 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 8157 sizeof(double)); 8158 out->args.vc.attr.group = UINT32_MAX; 8159 /* fallthrough */ 8160 case INDIRECT_ACTION_QUERY: 8161 out->command = ctx->curr; 8162 ctx->objdata = 0; 8163 ctx->object = out; 8164 ctx->objmask = NULL; 8165 return len; 8166 case INDIRECT_ACTION_EGRESS: 8167 out->args.vc.attr.egress = 1; 8168 return len; 8169 case INDIRECT_ACTION_INGRESS: 8170 out->args.vc.attr.ingress = 1; 8171 return len; 8172 case INDIRECT_ACTION_TRANSFER: 8173 out->args.vc.attr.transfer = 1; 8174 return len; 8175 case INDIRECT_ACTION_QU_MODE: 8176 return len; 8177 case INDIRECT_ACTION_LIST: 8178 out->command = INDIRECT_ACTION_LIST_CREATE; 8179 return len; 8180 case INDIRECT_ACTION_FLOW_CONF: 8181 out->command = INDIRECT_ACTION_FLOW_CONF_CREATE; 8182 return len; 8183 default: 8184 return -1; 8185 } 8186 } 8187 8188 8189 /** Parse tokens for indirect action destroy command. */ 8190 static int 8191 parse_ia_destroy(struct context *ctx, const struct token *token, 8192 const char *str, unsigned int len, 8193 void *buf, unsigned int size) 8194 { 8195 struct buffer *out = buf; 8196 uint32_t *action_id; 8197 8198 /* Token name must match. */ 8199 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8200 return -1; 8201 /* Nothing else to do if there is no buffer. */ 8202 if (!out) 8203 return len; 8204 if (!out->command || out->command == INDIRECT_ACTION) { 8205 if (ctx->curr != INDIRECT_ACTION_DESTROY) 8206 return -1; 8207 if (sizeof(*out) > size) 8208 return -1; 8209 out->command = ctx->curr; 8210 ctx->objdata = 0; 8211 ctx->object = out; 8212 ctx->objmask = NULL; 8213 out->args.ia_destroy.action_id = 8214 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 8215 sizeof(double)); 8216 return len; 8217 } 8218 action_id = out->args.ia_destroy.action_id 8219 + out->args.ia_destroy.action_id_n++; 8220 if ((uint8_t *)action_id > (uint8_t *)out + size) 8221 return -1; 8222 ctx->objdata = 0; 8223 ctx->object = action_id; 8224 ctx->objmask = NULL; 8225 return len; 8226 } 8227 8228 /** Parse tokens for indirect action commands. */ 8229 static int 8230 parse_qia(struct context *ctx, const struct token *token, 8231 const char *str, unsigned int len, 8232 void *buf, unsigned int size) 8233 { 8234 struct buffer *out = buf; 8235 8236 /* Token name must match. */ 8237 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8238 return -1; 8239 /* Nothing else to do if there is no buffer. */ 8240 if (!out) 8241 return len; 8242 if (!out->command) { 8243 if (ctx->curr != QUEUE) 8244 return -1; 8245 if (sizeof(*out) > size) 8246 return -1; 8247 out->args.vc.data = (uint8_t *)out + size; 8248 return len; 8249 } 8250 switch (ctx->curr) { 8251 case QUEUE_INDIRECT_ACTION: 8252 return len; 8253 case QUEUE_INDIRECT_ACTION_CREATE: 8254 case QUEUE_INDIRECT_ACTION_UPDATE: 8255 case QUEUE_INDIRECT_ACTION_QUERY_UPDATE: 8256 out->args.vc.actions = 8257 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 8258 sizeof(double)); 8259 out->args.vc.attr.group = UINT32_MAX; 8260 /* fallthrough */ 8261 case QUEUE_INDIRECT_ACTION_QUERY: 8262 out->command = ctx->curr; 8263 ctx->objdata = 0; 8264 ctx->object = out; 8265 ctx->objmask = NULL; 8266 return len; 8267 case QUEUE_INDIRECT_ACTION_EGRESS: 8268 out->args.vc.attr.egress = 1; 8269 return len; 8270 case QUEUE_INDIRECT_ACTION_INGRESS: 8271 out->args.vc.attr.ingress = 1; 8272 return len; 8273 case QUEUE_INDIRECT_ACTION_TRANSFER: 8274 out->args.vc.attr.transfer = 1; 8275 return len; 8276 case QUEUE_INDIRECT_ACTION_CREATE_POSTPONE: 8277 return len; 8278 case QUEUE_INDIRECT_ACTION_QU_MODE: 8279 return len; 8280 case QUEUE_INDIRECT_ACTION_LIST: 8281 out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE; 8282 return len; 8283 default: 8284 return -1; 8285 } 8286 } 8287 8288 /** Parse tokens for indirect action destroy command. */ 8289 static int 8290 parse_qia_destroy(struct context *ctx, const struct token *token, 8291 const char *str, unsigned int len, 8292 void *buf, unsigned int size) 8293 { 8294 struct buffer *out = buf; 8295 uint32_t *action_id; 8296 8297 /* Token name must match. */ 8298 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8299 return -1; 8300 /* Nothing else to do if there is no buffer. */ 8301 if (!out) 8302 return len; 8303 if (!out->command || out->command == QUEUE) { 8304 if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY) 8305 return -1; 8306 if (sizeof(*out) > size) 8307 return -1; 8308 out->command = ctx->curr; 8309 ctx->objdata = 0; 8310 ctx->object = out; 8311 ctx->objmask = NULL; 8312 out->args.ia_destroy.action_id = 8313 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 8314 sizeof(double)); 8315 return len; 8316 } 8317 switch (ctx->curr) { 8318 case QUEUE_INDIRECT_ACTION: 8319 out->command = ctx->curr; 8320 ctx->objdata = 0; 8321 ctx->object = out; 8322 ctx->objmask = NULL; 8323 return len; 8324 case QUEUE_INDIRECT_ACTION_DESTROY_ID: 8325 action_id = out->args.ia_destroy.action_id 8326 + out->args.ia_destroy.action_id_n++; 8327 if ((uint8_t *)action_id > (uint8_t *)out + size) 8328 return -1; 8329 ctx->objdata = 0; 8330 ctx->object = action_id; 8331 ctx->objmask = NULL; 8332 return len; 8333 case QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE: 8334 return len; 8335 default: 8336 return -1; 8337 } 8338 } 8339 8340 /** Parse tokens for meter policy action commands. */ 8341 static int 8342 parse_mp(struct context *ctx, const struct token *token, 8343 const char *str, unsigned int len, 8344 void *buf, unsigned int size) 8345 { 8346 struct buffer *out = buf; 8347 8348 /* Token name must match. */ 8349 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8350 return -1; 8351 /* Nothing else to do if there is no buffer. */ 8352 if (!out) 8353 return len; 8354 if (!out->command) { 8355 if (ctx->curr != ITEM_POL_POLICY) 8356 return -1; 8357 if (sizeof(*out) > size) 8358 return -1; 8359 out->command = ctx->curr; 8360 ctx->objdata = 0; 8361 ctx->object = out; 8362 ctx->objmask = NULL; 8363 out->args.vc.data = (uint8_t *)out + size; 8364 return len; 8365 } 8366 switch (ctx->curr) { 8367 case ACTION_POL_G: 8368 out->args.vc.actions = 8369 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 8370 sizeof(double)); 8371 out->command = ctx->curr; 8372 ctx->objdata = 0; 8373 ctx->object = out; 8374 ctx->objmask = NULL; 8375 return len; 8376 default: 8377 return -1; 8378 } 8379 } 8380 8381 /** Parse tokens for validate/create commands. */ 8382 static int 8383 parse_vc(struct context *ctx, const struct token *token, 8384 const char *str, unsigned int len, 8385 void *buf, unsigned int size) 8386 { 8387 struct buffer *out = buf; 8388 uint8_t *data; 8389 uint32_t data_size; 8390 8391 /* Token name must match. */ 8392 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8393 return -1; 8394 /* Nothing else to do if there is no buffer. */ 8395 if (!out) 8396 return len; 8397 if (!out->command) { 8398 if (ctx->curr != VALIDATE && ctx->curr != CREATE && 8399 ctx->curr != PATTERN_TEMPLATE_CREATE && 8400 ctx->curr != ACTIONS_TEMPLATE_CREATE) 8401 return -1; 8402 if (sizeof(*out) > size) 8403 return -1; 8404 out->command = ctx->curr; 8405 ctx->objdata = 0; 8406 ctx->object = out; 8407 ctx->objmask = NULL; 8408 out->args.vc.data = (uint8_t *)out + size; 8409 return len; 8410 } 8411 ctx->objdata = 0; 8412 switch (ctx->curr) { 8413 default: 8414 ctx->object = &out->args.vc.attr; 8415 break; 8416 case VC_TUNNEL_SET: 8417 case VC_TUNNEL_MATCH: 8418 ctx->object = &out->args.vc.tunnel_ops; 8419 break; 8420 case VC_USER_ID: 8421 ctx->object = out; 8422 break; 8423 } 8424 ctx->objmask = NULL; 8425 switch (ctx->curr) { 8426 case VC_GROUP: 8427 case VC_PRIORITY: 8428 case VC_USER_ID: 8429 return len; 8430 case VC_TUNNEL_SET: 8431 out->args.vc.tunnel_ops.enabled = 1; 8432 out->args.vc.tunnel_ops.actions = 1; 8433 return len; 8434 case VC_TUNNEL_MATCH: 8435 out->args.vc.tunnel_ops.enabled = 1; 8436 out->args.vc.tunnel_ops.items = 1; 8437 return len; 8438 case VC_INGRESS: 8439 out->args.vc.attr.ingress = 1; 8440 return len; 8441 case VC_EGRESS: 8442 out->args.vc.attr.egress = 1; 8443 return len; 8444 case VC_TRANSFER: 8445 out->args.vc.attr.transfer = 1; 8446 return len; 8447 case ITEM_PATTERN: 8448 out->args.vc.pattern = 8449 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 8450 sizeof(double)); 8451 ctx->object = out->args.vc.pattern; 8452 ctx->objmask = NULL; 8453 return len; 8454 case ITEM_END: 8455 if ((out->command == VALIDATE || out->command == CREATE) && 8456 ctx->last) 8457 return -1; 8458 if (out->command == PATTERN_TEMPLATE_CREATE && 8459 !ctx->last) 8460 return -1; 8461 break; 8462 case ACTIONS: 8463 out->args.vc.actions = out->args.vc.pattern ? 8464 (void *)RTE_ALIGN_CEIL((uintptr_t) 8465 (out->args.vc.pattern + 8466 out->args.vc.pattern_n), 8467 sizeof(double)) : 8468 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 8469 sizeof(double)); 8470 ctx->object = out->args.vc.actions; 8471 ctx->objmask = NULL; 8472 return len; 8473 default: 8474 if (!token->priv) 8475 return -1; 8476 break; 8477 } 8478 if (!out->args.vc.actions) { 8479 const struct parse_item_priv *priv = token->priv; 8480 struct rte_flow_item *item = 8481 out->args.vc.pattern + out->args.vc.pattern_n; 8482 8483 data_size = priv->size * 3; /* spec, last, mask */ 8484 data = (void *)RTE_ALIGN_FLOOR((uintptr_t) 8485 (out->args.vc.data - data_size), 8486 sizeof(double)); 8487 if ((uint8_t *)item + sizeof(*item) > data) 8488 return -1; 8489 *item = (struct rte_flow_item){ 8490 .type = priv->type, 8491 }; 8492 ++out->args.vc.pattern_n; 8493 ctx->object = item; 8494 ctx->objmask = NULL; 8495 } else { 8496 const struct parse_action_priv *priv = token->priv; 8497 struct rte_flow_action *action = 8498 out->args.vc.actions + out->args.vc.actions_n; 8499 8500 data_size = priv->size; /* configuration */ 8501 data = (void *)RTE_ALIGN_FLOOR((uintptr_t) 8502 (out->args.vc.data - data_size), 8503 sizeof(double)); 8504 if ((uint8_t *)action + sizeof(*action) > data) 8505 return -1; 8506 *action = (struct rte_flow_action){ 8507 .type = priv->type, 8508 .conf = data_size ? data : NULL, 8509 }; 8510 ++out->args.vc.actions_n; 8511 ctx->object = action; 8512 ctx->objmask = NULL; 8513 } 8514 memset(data, 0, data_size); 8515 out->args.vc.data = data; 8516 ctx->objdata = data_size; 8517 return len; 8518 } 8519 8520 /** Parse pattern item parameter type. */ 8521 static int 8522 parse_vc_spec(struct context *ctx, const struct token *token, 8523 const char *str, unsigned int len, 8524 void *buf, unsigned int size) 8525 { 8526 struct buffer *out = buf; 8527 struct rte_flow_item *item; 8528 uint32_t data_size; 8529 int index; 8530 int objmask = 0; 8531 8532 (void)size; 8533 /* Token name must match. */ 8534 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8535 return -1; 8536 /* Parse parameter types. */ 8537 switch (ctx->curr) { 8538 static const enum index prefix[] = NEXT_ENTRY(COMMON_PREFIX); 8539 8540 case ITEM_PARAM_IS: 8541 index = 0; 8542 objmask = 1; 8543 break; 8544 case ITEM_PARAM_SPEC: 8545 index = 0; 8546 break; 8547 case ITEM_PARAM_LAST: 8548 index = 1; 8549 break; 8550 case ITEM_PARAM_PREFIX: 8551 /* Modify next token to expect a prefix. */ 8552 if (ctx->next_num < 2) 8553 return -1; 8554 ctx->next[ctx->next_num - 2] = prefix; 8555 /* Fall through. */ 8556 case ITEM_PARAM_MASK: 8557 index = 2; 8558 break; 8559 default: 8560 return -1; 8561 } 8562 /* Nothing else to do if there is no buffer. */ 8563 if (!out) 8564 return len; 8565 if (!out->args.vc.pattern_n) 8566 return -1; 8567 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1]; 8568 data_size = ctx->objdata / 3; /* spec, last, mask */ 8569 /* Point to selected object. */ 8570 ctx->object = out->args.vc.data + (data_size * index); 8571 if (objmask) { 8572 ctx->objmask = out->args.vc.data + (data_size * 2); /* mask */ 8573 item->mask = ctx->objmask; 8574 } else 8575 ctx->objmask = NULL; 8576 /* Update relevant item pointer. */ 8577 *((const void **[]){ &item->spec, &item->last, &item->mask })[index] = 8578 ctx->object; 8579 return len; 8580 } 8581 8582 /** Parse action configuration field. */ 8583 static int 8584 parse_vc_conf(struct context *ctx, const struct token *token, 8585 const char *str, unsigned int len, 8586 void *buf, unsigned int size) 8587 { 8588 struct buffer *out = buf; 8589 8590 (void)size; 8591 /* Token name must match. */ 8592 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8593 return -1; 8594 /* Nothing else to do if there is no buffer. */ 8595 if (!out) 8596 return len; 8597 /* Point to selected object. */ 8598 ctx->object = out->args.vc.data; 8599 ctx->objmask = NULL; 8600 return len; 8601 } 8602 8603 /** Parse action configuration field. */ 8604 static int 8605 parse_vc_conf_timeout(struct context *ctx, const struct token *token, 8606 const char *str, unsigned int len, 8607 void *buf, unsigned int size) 8608 { 8609 struct buffer *out = buf; 8610 struct rte_flow_update_age *update; 8611 8612 (void)size; 8613 if (ctx->curr != ACTION_AGE_UPDATE_TIMEOUT) 8614 return -1; 8615 /* Token name must match. */ 8616 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8617 return -1; 8618 /* Nothing else to do if there is no buffer. */ 8619 if (!out) 8620 return len; 8621 /* Point to selected object. */ 8622 ctx->object = out->args.vc.data; 8623 ctx->objmask = NULL; 8624 /* Update the timeout is valid. */ 8625 update = (struct rte_flow_update_age *)out->args.vc.data; 8626 update->timeout_valid = 1; 8627 return len; 8628 } 8629 8630 /** Parse eCPRI common header type field. */ 8631 static int 8632 parse_vc_item_ecpri_type(struct context *ctx, const struct token *token, 8633 const char *str, unsigned int len, 8634 void *buf, unsigned int size) 8635 { 8636 struct rte_flow_item_ecpri *ecpri; 8637 struct rte_flow_item_ecpri *ecpri_mask; 8638 struct rte_flow_item *item; 8639 uint32_t data_size; 8640 uint8_t msg_type; 8641 struct buffer *out = buf; 8642 const struct arg *arg; 8643 8644 (void)size; 8645 /* Token name must match. */ 8646 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8647 return -1; 8648 switch (ctx->curr) { 8649 case ITEM_ECPRI_COMMON_TYPE_IQ_DATA: 8650 msg_type = RTE_ECPRI_MSG_TYPE_IQ_DATA; 8651 break; 8652 case ITEM_ECPRI_COMMON_TYPE_RTC_CTRL: 8653 msg_type = RTE_ECPRI_MSG_TYPE_RTC_CTRL; 8654 break; 8655 case ITEM_ECPRI_COMMON_TYPE_DLY_MSR: 8656 msg_type = RTE_ECPRI_MSG_TYPE_DLY_MSR; 8657 break; 8658 default: 8659 return -1; 8660 } 8661 if (!ctx->object) 8662 return len; 8663 arg = pop_args(ctx); 8664 if (!arg) 8665 return -1; 8666 ecpri = (struct rte_flow_item_ecpri *)out->args.vc.data; 8667 ecpri->hdr.common.type = msg_type; 8668 data_size = ctx->objdata / 3; /* spec, last, mask */ 8669 ecpri_mask = (struct rte_flow_item_ecpri *)(out->args.vc.data + 8670 (data_size * 2)); 8671 ecpri_mask->hdr.common.type = 0xFF; 8672 if (arg->hton) { 8673 ecpri->hdr.common.u32 = rte_cpu_to_be_32(ecpri->hdr.common.u32); 8674 ecpri_mask->hdr.common.u32 = 8675 rte_cpu_to_be_32(ecpri_mask->hdr.common.u32); 8676 } 8677 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1]; 8678 item->spec = ecpri; 8679 item->mask = ecpri_mask; 8680 return len; 8681 } 8682 8683 /** Parse L2TPv2 common header type field. */ 8684 static int 8685 parse_vc_item_l2tpv2_type(struct context *ctx, const struct token *token, 8686 const char *str, unsigned int len, 8687 void *buf, unsigned int size) 8688 { 8689 struct rte_flow_item_l2tpv2 *l2tpv2; 8690 struct rte_flow_item_l2tpv2 *l2tpv2_mask; 8691 struct rte_flow_item *item; 8692 uint32_t data_size; 8693 uint16_t msg_type = 0; 8694 struct buffer *out = buf; 8695 const struct arg *arg; 8696 8697 (void)size; 8698 /* Token name must match. */ 8699 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8700 return -1; 8701 switch (ctx->curr) { 8702 case ITEM_L2TPV2_TYPE_DATA: 8703 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA; 8704 break; 8705 case ITEM_L2TPV2_TYPE_DATA_L: 8706 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L; 8707 break; 8708 case ITEM_L2TPV2_TYPE_DATA_S: 8709 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_S; 8710 break; 8711 case ITEM_L2TPV2_TYPE_DATA_O: 8712 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_O; 8713 break; 8714 case ITEM_L2TPV2_TYPE_DATA_L_S: 8715 msg_type |= RTE_L2TPV2_MSG_TYPE_DATA_L_S; 8716 break; 8717 case ITEM_L2TPV2_TYPE_CTRL: 8718 msg_type |= RTE_L2TPV2_MSG_TYPE_CONTROL; 8719 break; 8720 default: 8721 return -1; 8722 } 8723 if (!ctx->object) 8724 return len; 8725 arg = pop_args(ctx); 8726 if (!arg) 8727 return -1; 8728 l2tpv2 = (struct rte_flow_item_l2tpv2 *)out->args.vc.data; 8729 l2tpv2->hdr.common.flags_version |= msg_type; 8730 data_size = ctx->objdata / 3; /* spec, last, mask */ 8731 l2tpv2_mask = (struct rte_flow_item_l2tpv2 *)(out->args.vc.data + 8732 (data_size * 2)); 8733 l2tpv2_mask->hdr.common.flags_version = 0xFFFF; 8734 if (arg->hton) { 8735 l2tpv2->hdr.common.flags_version = 8736 rte_cpu_to_be_16(l2tpv2->hdr.common.flags_version); 8737 l2tpv2_mask->hdr.common.flags_version = 8738 rte_cpu_to_be_16(l2tpv2_mask->hdr.common.flags_version); 8739 } 8740 item = &out->args.vc.pattern[out->args.vc.pattern_n - 1]; 8741 item->spec = l2tpv2; 8742 item->mask = l2tpv2_mask; 8743 return len; 8744 } 8745 8746 /** Parse operation for compare match item. */ 8747 static int 8748 parse_vc_compare_op(struct context *ctx, const struct token *token, 8749 const char *str, unsigned int len, void *buf, 8750 unsigned int size) 8751 { 8752 struct rte_flow_item_compare *compare_item; 8753 unsigned int i; 8754 8755 (void)token; 8756 (void)buf; 8757 (void)size; 8758 if (ctx->curr != ITEM_COMPARE_OP_VALUE) 8759 return -1; 8760 for (i = 0; compare_ops[i]; ++i) 8761 if (!strcmp_partial(compare_ops[i], str, len)) 8762 break; 8763 if (!compare_ops[i]) 8764 return -1; 8765 if (!ctx->object) 8766 return len; 8767 compare_item = ctx->object; 8768 compare_item->operation = (enum rte_flow_item_compare_op)i; 8769 return len; 8770 } 8771 8772 /** Parse id for compare match item. */ 8773 static int 8774 parse_vc_compare_field_id(struct context *ctx, const struct token *token, 8775 const char *str, unsigned int len, void *buf, 8776 unsigned int size) 8777 { 8778 struct rte_flow_item_compare *compare_item; 8779 unsigned int i; 8780 8781 (void)token; 8782 (void)buf; 8783 (void)size; 8784 if (ctx->curr != ITEM_COMPARE_FIELD_A_TYPE_VALUE && 8785 ctx->curr != ITEM_COMPARE_FIELD_B_TYPE_VALUE) 8786 return -1; 8787 for (i = 0; flow_field_ids[i]; ++i) 8788 if (!strcmp_partial(flow_field_ids[i], str, len)) 8789 break; 8790 if (!flow_field_ids[i]) 8791 return -1; 8792 if (!ctx->object) 8793 return len; 8794 compare_item = ctx->object; 8795 if (ctx->curr == ITEM_COMPARE_FIELD_A_TYPE_VALUE) 8796 compare_item->a.field = (enum rte_flow_field_id)i; 8797 else 8798 compare_item->b.field = (enum rte_flow_field_id)i; 8799 return len; 8800 } 8801 8802 /** Parse level for compare match item. */ 8803 static int 8804 parse_vc_compare_field_level(struct context *ctx, const struct token *token, 8805 const char *str, unsigned int len, void *buf, 8806 unsigned int size) 8807 { 8808 struct rte_flow_item_compare *compare_item; 8809 struct flex_item *fp = NULL; 8810 uint32_t val; 8811 struct buffer *out = buf; 8812 char *end; 8813 8814 (void)token; 8815 (void)size; 8816 if (ctx->curr != ITEM_COMPARE_FIELD_A_LEVEL_VALUE && 8817 ctx->curr != ITEM_COMPARE_FIELD_B_LEVEL_VALUE) 8818 return -1; 8819 if (!ctx->object) 8820 return len; 8821 compare_item = ctx->object; 8822 errno = 0; 8823 val = strtoumax(str, &end, 0); 8824 if (errno || (size_t)(end - str) != len) 8825 return -1; 8826 /* No need to validate action template mask value */ 8827 if (out->args.vc.masks) { 8828 if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) 8829 compare_item->a.level = val; 8830 else 8831 compare_item->b.level = val; 8832 return len; 8833 } 8834 if ((ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE && 8835 compare_item->a.field == RTE_FLOW_FIELD_FLEX_ITEM) || 8836 (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE && 8837 compare_item->b.field == RTE_FLOW_FIELD_FLEX_ITEM)) { 8838 if (val >= FLEX_MAX_PARSERS_NUM) { 8839 printf("Bad flex item handle\n"); 8840 return -1; 8841 } 8842 fp = flex_items[ctx->port][val]; 8843 if (!fp) { 8844 printf("Bad flex item handle\n"); 8845 return -1; 8846 } 8847 } 8848 if (ctx->curr == ITEM_COMPARE_FIELD_A_LEVEL_VALUE) { 8849 if (compare_item->a.field != RTE_FLOW_FIELD_FLEX_ITEM) 8850 compare_item->a.level = val; 8851 else 8852 compare_item->a.flex_handle = fp->flex_handle; 8853 } else if (ctx->curr == ITEM_COMPARE_FIELD_B_LEVEL_VALUE) { 8854 if (compare_item->b.field != RTE_FLOW_FIELD_FLEX_ITEM) 8855 compare_item->b.level = val; 8856 else 8857 compare_item->b.flex_handle = fp->flex_handle; 8858 } 8859 return len; 8860 } 8861 8862 /** Parse meter color action type. */ 8863 static int 8864 parse_vc_action_meter_color_type(struct context *ctx, const struct token *token, 8865 const char *str, unsigned int len, 8866 void *buf, unsigned int size) 8867 { 8868 struct rte_flow_action *action_data; 8869 struct rte_flow_action_meter_color *conf; 8870 enum rte_color color; 8871 8872 (void)buf; 8873 (void)size; 8874 /* Token name must match. */ 8875 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8876 return -1; 8877 switch (ctx->curr) { 8878 case ACTION_METER_COLOR_GREEN: 8879 color = RTE_COLOR_GREEN; 8880 break; 8881 case ACTION_METER_COLOR_YELLOW: 8882 color = RTE_COLOR_YELLOW; 8883 break; 8884 case ACTION_METER_COLOR_RED: 8885 color = RTE_COLOR_RED; 8886 break; 8887 default: 8888 return -1; 8889 } 8890 8891 if (!ctx->object) 8892 return len; 8893 action_data = ctx->object; 8894 conf = (struct rte_flow_action_meter_color *) 8895 (uintptr_t)(action_data->conf); 8896 conf->color = color; 8897 return len; 8898 } 8899 8900 /** Parse RSS action. */ 8901 static int 8902 parse_vc_action_rss(struct context *ctx, const struct token *token, 8903 const char *str, unsigned int len, 8904 void *buf, unsigned int size) 8905 { 8906 struct buffer *out = buf; 8907 struct rte_flow_action *action; 8908 struct action_rss_data *action_rss_data; 8909 unsigned int i; 8910 int ret; 8911 8912 ret = parse_vc(ctx, token, str, len, buf, size); 8913 if (ret < 0) 8914 return ret; 8915 /* Nothing else to do if there is no buffer. */ 8916 if (!out) 8917 return ret; 8918 if (!out->args.vc.actions_n) 8919 return -1; 8920 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 8921 /* Point to selected object. */ 8922 ctx->object = out->args.vc.data; 8923 ctx->objmask = NULL; 8924 /* Set up default configuration. */ 8925 action_rss_data = ctx->object; 8926 *action_rss_data = (struct action_rss_data){ 8927 .conf = (struct rte_flow_action_rss){ 8928 .func = RTE_ETH_HASH_FUNCTION_DEFAULT, 8929 .level = 0, 8930 .types = rss_hf, 8931 .key_len = 0, 8932 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM), 8933 .key = NULL, 8934 .queue = action_rss_data->queue, 8935 }, 8936 .queue = { 0 }, 8937 }; 8938 for (i = 0; i < action_rss_data->conf.queue_num; ++i) 8939 action_rss_data->queue[i] = i; 8940 action->conf = &action_rss_data->conf; 8941 return ret; 8942 } 8943 8944 /** 8945 * Parse func field for RSS action. 8946 * 8947 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the 8948 * ACTION_RSS_FUNC_* index that called this function. 8949 */ 8950 static int 8951 parse_vc_action_rss_func(struct context *ctx, const struct token *token, 8952 const char *str, unsigned int len, 8953 void *buf, unsigned int size) 8954 { 8955 struct action_rss_data *action_rss_data; 8956 enum rte_eth_hash_function func; 8957 8958 (void)buf; 8959 (void)size; 8960 /* Token name must match. */ 8961 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 8962 return -1; 8963 switch (ctx->curr) { 8964 case ACTION_RSS_FUNC_DEFAULT: 8965 func = RTE_ETH_HASH_FUNCTION_DEFAULT; 8966 break; 8967 case ACTION_RSS_FUNC_TOEPLITZ: 8968 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ; 8969 break; 8970 case ACTION_RSS_FUNC_SIMPLE_XOR: 8971 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR; 8972 break; 8973 case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ: 8974 func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ; 8975 break; 8976 default: 8977 return -1; 8978 } 8979 if (!ctx->object) 8980 return len; 8981 action_rss_data = ctx->object; 8982 action_rss_data->conf.func = func; 8983 return len; 8984 } 8985 8986 /** 8987 * Parse type field for RSS action. 8988 * 8989 * Valid tokens are type field names and the "end" token. 8990 */ 8991 static int 8992 parse_vc_action_rss_type(struct context *ctx, const struct token *token, 8993 const char *str, unsigned int len, 8994 void *buf, unsigned int size) 8995 { 8996 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE); 8997 struct action_rss_data *action_rss_data; 8998 unsigned int i; 8999 9000 (void)token; 9001 (void)buf; 9002 (void)size; 9003 if (ctx->curr != ACTION_RSS_TYPE) 9004 return -1; 9005 if (!(ctx->objdata >> 16) && ctx->object) { 9006 action_rss_data = ctx->object; 9007 action_rss_data->conf.types = 0; 9008 } 9009 if (!strcmp_partial("end", str, len)) { 9010 ctx->objdata &= 0xffff; 9011 return len; 9012 } 9013 for (i = 0; rss_type_table[i].str; ++i) 9014 if (!strcmp_partial(rss_type_table[i].str, str, len)) 9015 break; 9016 if (!rss_type_table[i].str) 9017 return -1; 9018 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff); 9019 /* Repeat token. */ 9020 if (ctx->next_num == RTE_DIM(ctx->next)) 9021 return -1; 9022 ctx->next[ctx->next_num++] = next; 9023 if (!ctx->object) 9024 return len; 9025 action_rss_data = ctx->object; 9026 action_rss_data->conf.types |= rss_type_table[i].rss_type; 9027 return len; 9028 } 9029 9030 /** 9031 * Parse queue field for RSS action. 9032 * 9033 * Valid tokens are queue indices and the "end" token. 9034 */ 9035 static int 9036 parse_vc_action_rss_queue(struct context *ctx, const struct token *token, 9037 const char *str, unsigned int len, 9038 void *buf, unsigned int size) 9039 { 9040 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE); 9041 struct action_rss_data *action_rss_data; 9042 const struct arg *arg; 9043 int ret; 9044 int i; 9045 9046 (void)token; 9047 (void)buf; 9048 (void)size; 9049 if (ctx->curr != ACTION_RSS_QUEUE) 9050 return -1; 9051 i = ctx->objdata >> 16; 9052 if (!strcmp_partial("end", str, len)) { 9053 ctx->objdata &= 0xffff; 9054 goto end; 9055 } 9056 if (i >= ACTION_RSS_QUEUE_NUM) 9057 return -1; 9058 arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) + 9059 i * sizeof(action_rss_data->queue[i]), 9060 sizeof(action_rss_data->queue[i])); 9061 if (push_args(ctx, arg)) 9062 return -1; 9063 ret = parse_int(ctx, token, str, len, NULL, 0); 9064 if (ret < 0) { 9065 pop_args(ctx); 9066 return -1; 9067 } 9068 ++i; 9069 ctx->objdata = i << 16 | (ctx->objdata & 0xffff); 9070 /* Repeat token. */ 9071 if (ctx->next_num == RTE_DIM(ctx->next)) 9072 return -1; 9073 ctx->next[ctx->next_num++] = next; 9074 end: 9075 if (!ctx->object) 9076 return len; 9077 action_rss_data = ctx->object; 9078 action_rss_data->conf.queue_num = i; 9079 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL; 9080 return len; 9081 } 9082 9083 /** Setup VXLAN encap configuration. */ 9084 static int 9085 parse_setup_vxlan_encap_data(struct action_vxlan_encap_data *action_vxlan_encap_data) 9086 { 9087 /* Set up default configuration. */ 9088 *action_vxlan_encap_data = (struct action_vxlan_encap_data){ 9089 .conf = (struct rte_flow_action_vxlan_encap){ 9090 .definition = action_vxlan_encap_data->items, 9091 }, 9092 .items = { 9093 { 9094 .type = RTE_FLOW_ITEM_TYPE_ETH, 9095 .spec = &action_vxlan_encap_data->item_eth, 9096 .mask = &rte_flow_item_eth_mask, 9097 }, 9098 { 9099 .type = RTE_FLOW_ITEM_TYPE_VLAN, 9100 .spec = &action_vxlan_encap_data->item_vlan, 9101 .mask = &rte_flow_item_vlan_mask, 9102 }, 9103 { 9104 .type = RTE_FLOW_ITEM_TYPE_IPV4, 9105 .spec = &action_vxlan_encap_data->item_ipv4, 9106 .mask = &rte_flow_item_ipv4_mask, 9107 }, 9108 { 9109 .type = RTE_FLOW_ITEM_TYPE_UDP, 9110 .spec = &action_vxlan_encap_data->item_udp, 9111 .mask = &rte_flow_item_udp_mask, 9112 }, 9113 { 9114 .type = RTE_FLOW_ITEM_TYPE_VXLAN, 9115 .spec = &action_vxlan_encap_data->item_vxlan, 9116 .mask = &rte_flow_item_vxlan_mask, 9117 }, 9118 { 9119 .type = RTE_FLOW_ITEM_TYPE_END, 9120 }, 9121 }, 9122 .item_eth.hdr.ether_type = 0, 9123 .item_vlan = { 9124 .hdr.vlan_tci = vxlan_encap_conf.vlan_tci, 9125 .hdr.eth_proto = 0, 9126 }, 9127 .item_ipv4.hdr = { 9128 .src_addr = vxlan_encap_conf.ipv4_src, 9129 .dst_addr = vxlan_encap_conf.ipv4_dst, 9130 }, 9131 .item_udp.hdr = { 9132 .src_port = vxlan_encap_conf.udp_src, 9133 .dst_port = vxlan_encap_conf.udp_dst, 9134 }, 9135 .item_vxlan.hdr.flags = 0, 9136 }; 9137 memcpy(action_vxlan_encap_data->item_eth.hdr.dst_addr.addr_bytes, 9138 vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 9139 memcpy(action_vxlan_encap_data->item_eth.hdr.src_addr.addr_bytes, 9140 vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 9141 if (!vxlan_encap_conf.select_ipv4) { 9142 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr, 9143 &vxlan_encap_conf.ipv6_src, 9144 sizeof(vxlan_encap_conf.ipv6_src)); 9145 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr, 9146 &vxlan_encap_conf.ipv6_dst, 9147 sizeof(vxlan_encap_conf.ipv6_dst)); 9148 action_vxlan_encap_data->items[2] = (struct rte_flow_item){ 9149 .type = RTE_FLOW_ITEM_TYPE_IPV6, 9150 .spec = &action_vxlan_encap_data->item_ipv6, 9151 .mask = &rte_flow_item_ipv6_mask, 9152 }; 9153 } 9154 if (!vxlan_encap_conf.select_vlan) 9155 action_vxlan_encap_data->items[1].type = 9156 RTE_FLOW_ITEM_TYPE_VOID; 9157 if (vxlan_encap_conf.select_tos_ttl) { 9158 if (vxlan_encap_conf.select_ipv4) { 9159 static struct rte_flow_item_ipv4 ipv4_mask_tos; 9160 9161 memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask, 9162 sizeof(ipv4_mask_tos)); 9163 ipv4_mask_tos.hdr.type_of_service = 0xff; 9164 ipv4_mask_tos.hdr.time_to_live = 0xff; 9165 action_vxlan_encap_data->item_ipv4.hdr.type_of_service = 9166 vxlan_encap_conf.ip_tos; 9167 action_vxlan_encap_data->item_ipv4.hdr.time_to_live = 9168 vxlan_encap_conf.ip_ttl; 9169 action_vxlan_encap_data->items[2].mask = 9170 &ipv4_mask_tos; 9171 } else { 9172 static struct rte_flow_item_ipv6 ipv6_mask_tos; 9173 9174 memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask, 9175 sizeof(ipv6_mask_tos)); 9176 ipv6_mask_tos.hdr.vtc_flow |= 9177 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT); 9178 ipv6_mask_tos.hdr.hop_limits = 0xff; 9179 action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |= 9180 rte_cpu_to_be_32 9181 ((uint32_t)vxlan_encap_conf.ip_tos << 9182 RTE_IPV6_HDR_TC_SHIFT); 9183 action_vxlan_encap_data->item_ipv6.hdr.hop_limits = 9184 vxlan_encap_conf.ip_ttl; 9185 action_vxlan_encap_data->items[2].mask = 9186 &ipv6_mask_tos; 9187 } 9188 } 9189 memcpy(action_vxlan_encap_data->item_vxlan.hdr.vni, vxlan_encap_conf.vni, 9190 RTE_DIM(vxlan_encap_conf.vni)); 9191 return 0; 9192 } 9193 9194 /** Parse VXLAN encap action. */ 9195 static int 9196 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token, 9197 const char *str, unsigned int len, 9198 void *buf, unsigned int size) 9199 { 9200 struct buffer *out = buf; 9201 struct rte_flow_action *action; 9202 struct action_vxlan_encap_data *action_vxlan_encap_data; 9203 int ret; 9204 9205 ret = parse_vc(ctx, token, str, len, buf, size); 9206 if (ret < 0) 9207 return ret; 9208 /* Nothing else to do if there is no buffer. */ 9209 if (!out) 9210 return ret; 9211 if (!out->args.vc.actions_n) 9212 return -1; 9213 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 9214 /* Point to selected object. */ 9215 ctx->object = out->args.vc.data; 9216 ctx->objmask = NULL; 9217 action_vxlan_encap_data = ctx->object; 9218 parse_setup_vxlan_encap_data(action_vxlan_encap_data); 9219 action->conf = &action_vxlan_encap_data->conf; 9220 return ret; 9221 } 9222 9223 /** Setup NVGRE encap configuration. */ 9224 static int 9225 parse_setup_nvgre_encap_data(struct action_nvgre_encap_data *action_nvgre_encap_data) 9226 { 9227 /* Set up default configuration. */ 9228 *action_nvgre_encap_data = (struct action_nvgre_encap_data){ 9229 .conf = (struct rte_flow_action_nvgre_encap){ 9230 .definition = action_nvgre_encap_data->items, 9231 }, 9232 .items = { 9233 { 9234 .type = RTE_FLOW_ITEM_TYPE_ETH, 9235 .spec = &action_nvgre_encap_data->item_eth, 9236 .mask = &rte_flow_item_eth_mask, 9237 }, 9238 { 9239 .type = RTE_FLOW_ITEM_TYPE_VLAN, 9240 .spec = &action_nvgre_encap_data->item_vlan, 9241 .mask = &rte_flow_item_vlan_mask, 9242 }, 9243 { 9244 .type = RTE_FLOW_ITEM_TYPE_IPV4, 9245 .spec = &action_nvgre_encap_data->item_ipv4, 9246 .mask = &rte_flow_item_ipv4_mask, 9247 }, 9248 { 9249 .type = RTE_FLOW_ITEM_TYPE_NVGRE, 9250 .spec = &action_nvgre_encap_data->item_nvgre, 9251 .mask = &rte_flow_item_nvgre_mask, 9252 }, 9253 { 9254 .type = RTE_FLOW_ITEM_TYPE_END, 9255 }, 9256 }, 9257 .item_eth.hdr.ether_type = 0, 9258 .item_vlan = { 9259 .hdr.vlan_tci = nvgre_encap_conf.vlan_tci, 9260 .hdr.eth_proto = 0, 9261 }, 9262 .item_ipv4.hdr = { 9263 .src_addr = nvgre_encap_conf.ipv4_src, 9264 .dst_addr = nvgre_encap_conf.ipv4_dst, 9265 }, 9266 .item_nvgre.c_k_s_rsvd0_ver = RTE_BE16(0x2000), 9267 .item_nvgre.protocol = RTE_BE16(RTE_ETHER_TYPE_TEB), 9268 .item_nvgre.flow_id = 0, 9269 }; 9270 memcpy(action_nvgre_encap_data->item_eth.hdr.dst_addr.addr_bytes, 9271 nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 9272 memcpy(action_nvgre_encap_data->item_eth.hdr.src_addr.addr_bytes, 9273 nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 9274 if (!nvgre_encap_conf.select_ipv4) { 9275 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr, 9276 &nvgre_encap_conf.ipv6_src, 9277 sizeof(nvgre_encap_conf.ipv6_src)); 9278 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr, 9279 &nvgre_encap_conf.ipv6_dst, 9280 sizeof(nvgre_encap_conf.ipv6_dst)); 9281 action_nvgre_encap_data->items[2] = (struct rte_flow_item){ 9282 .type = RTE_FLOW_ITEM_TYPE_IPV6, 9283 .spec = &action_nvgre_encap_data->item_ipv6, 9284 .mask = &rte_flow_item_ipv6_mask, 9285 }; 9286 } 9287 if (!nvgre_encap_conf.select_vlan) 9288 action_nvgre_encap_data->items[1].type = 9289 RTE_FLOW_ITEM_TYPE_VOID; 9290 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni, 9291 RTE_DIM(nvgre_encap_conf.tni)); 9292 return 0; 9293 } 9294 9295 /** Parse NVGRE encap action. */ 9296 static int 9297 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token, 9298 const char *str, unsigned int len, 9299 void *buf, unsigned int size) 9300 { 9301 struct buffer *out = buf; 9302 struct rte_flow_action *action; 9303 struct action_nvgre_encap_data *action_nvgre_encap_data; 9304 int ret; 9305 9306 ret = parse_vc(ctx, token, str, len, buf, size); 9307 if (ret < 0) 9308 return ret; 9309 /* Nothing else to do if there is no buffer. */ 9310 if (!out) 9311 return ret; 9312 if (!out->args.vc.actions_n) 9313 return -1; 9314 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 9315 /* Point to selected object. */ 9316 ctx->object = out->args.vc.data; 9317 ctx->objmask = NULL; 9318 action_nvgre_encap_data = ctx->object; 9319 parse_setup_nvgre_encap_data(action_nvgre_encap_data); 9320 action->conf = &action_nvgre_encap_data->conf; 9321 return ret; 9322 } 9323 9324 /** Parse l2 encap action. */ 9325 static int 9326 parse_vc_action_l2_encap(struct context *ctx, const struct token *token, 9327 const char *str, unsigned int len, 9328 void *buf, unsigned int size) 9329 { 9330 struct buffer *out = buf; 9331 struct rte_flow_action *action; 9332 struct action_raw_encap_data *action_encap_data; 9333 struct rte_flow_item_eth eth = { .hdr.ether_type = 0, }; 9334 struct rte_flow_item_vlan vlan = { 9335 .hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci, 9336 .hdr.eth_proto = 0, 9337 }; 9338 uint8_t *header; 9339 int ret; 9340 9341 ret = parse_vc(ctx, token, str, len, buf, size); 9342 if (ret < 0) 9343 return ret; 9344 /* Nothing else to do if there is no buffer. */ 9345 if (!out) 9346 return ret; 9347 if (!out->args.vc.actions_n) 9348 return -1; 9349 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 9350 /* Point to selected object. */ 9351 ctx->object = out->args.vc.data; 9352 ctx->objmask = NULL; 9353 /* Copy the headers to the buffer. */ 9354 action_encap_data = ctx->object; 9355 *action_encap_data = (struct action_raw_encap_data) { 9356 .conf = (struct rte_flow_action_raw_encap){ 9357 .data = action_encap_data->data, 9358 }, 9359 .data = {}, 9360 }; 9361 header = action_encap_data->data; 9362 if (l2_encap_conf.select_vlan) 9363 eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 9364 else if (l2_encap_conf.select_ipv4) 9365 eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 9366 else 9367 eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 9368 memcpy(eth.hdr.dst_addr.addr_bytes, 9369 l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 9370 memcpy(eth.hdr.src_addr.addr_bytes, 9371 l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 9372 memcpy(header, ð.hdr, sizeof(struct rte_ether_hdr)); 9373 header += sizeof(struct rte_ether_hdr); 9374 if (l2_encap_conf.select_vlan) { 9375 if (l2_encap_conf.select_ipv4) 9376 vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 9377 else 9378 vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 9379 memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr)); 9380 header += sizeof(struct rte_vlan_hdr); 9381 } 9382 action_encap_data->conf.size = header - 9383 action_encap_data->data; 9384 action->conf = &action_encap_data->conf; 9385 return ret; 9386 } 9387 9388 /** Parse l2 decap action. */ 9389 static int 9390 parse_vc_action_l2_decap(struct context *ctx, const struct token *token, 9391 const char *str, unsigned int len, 9392 void *buf, unsigned int size) 9393 { 9394 struct buffer *out = buf; 9395 struct rte_flow_action *action; 9396 struct action_raw_decap_data *action_decap_data; 9397 struct rte_flow_item_eth eth = { .hdr.ether_type = 0, }; 9398 struct rte_flow_item_vlan vlan = { 9399 .hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci, 9400 .hdr.eth_proto = 0, 9401 }; 9402 uint8_t *header; 9403 int ret; 9404 9405 ret = parse_vc(ctx, token, str, len, buf, size); 9406 if (ret < 0) 9407 return ret; 9408 /* Nothing else to do if there is no buffer. */ 9409 if (!out) 9410 return ret; 9411 if (!out->args.vc.actions_n) 9412 return -1; 9413 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 9414 /* Point to selected object. */ 9415 ctx->object = out->args.vc.data; 9416 ctx->objmask = NULL; 9417 /* Copy the headers to the buffer. */ 9418 action_decap_data = ctx->object; 9419 *action_decap_data = (struct action_raw_decap_data) { 9420 .conf = (struct rte_flow_action_raw_decap){ 9421 .data = action_decap_data->data, 9422 }, 9423 .data = {}, 9424 }; 9425 header = action_decap_data->data; 9426 if (l2_decap_conf.select_vlan) 9427 eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 9428 memcpy(header, ð.hdr, sizeof(struct rte_ether_hdr)); 9429 header += sizeof(struct rte_ether_hdr); 9430 if (l2_decap_conf.select_vlan) { 9431 memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr)); 9432 header += sizeof(struct rte_vlan_hdr); 9433 } 9434 action_decap_data->conf.size = header - 9435 action_decap_data->data; 9436 action->conf = &action_decap_data->conf; 9437 return ret; 9438 } 9439 9440 #define ETHER_TYPE_MPLS_UNICAST 0x8847 9441 9442 /** Parse MPLSOGRE encap action. */ 9443 static int 9444 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token, 9445 const char *str, unsigned int len, 9446 void *buf, unsigned int size) 9447 { 9448 struct buffer *out = buf; 9449 struct rte_flow_action *action; 9450 struct action_raw_encap_data *action_encap_data; 9451 struct rte_flow_item_eth eth = { .hdr.ether_type = 0, }; 9452 struct rte_flow_item_vlan vlan = { 9453 .hdr.vlan_tci = mplsogre_encap_conf.vlan_tci, 9454 .hdr.eth_proto = 0, 9455 }; 9456 struct rte_flow_item_ipv4 ipv4 = { 9457 .hdr = { 9458 .src_addr = mplsogre_encap_conf.ipv4_src, 9459 .dst_addr = mplsogre_encap_conf.ipv4_dst, 9460 .next_proto_id = IPPROTO_GRE, 9461 .version_ihl = RTE_IPV4_VHL_DEF, 9462 .time_to_live = IPDEFTTL, 9463 }, 9464 }; 9465 struct rte_flow_item_ipv6 ipv6 = { 9466 .hdr = { 9467 .proto = IPPROTO_GRE, 9468 .hop_limits = IPDEFTTL, 9469 }, 9470 }; 9471 struct rte_flow_item_gre gre = { 9472 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST), 9473 }; 9474 struct rte_flow_item_mpls mpls = { 9475 .ttl = 0, 9476 }; 9477 uint8_t *header; 9478 int ret; 9479 9480 ret = parse_vc(ctx, token, str, len, buf, size); 9481 if (ret < 0) 9482 return ret; 9483 /* Nothing else to do if there is no buffer. */ 9484 if (!out) 9485 return ret; 9486 if (!out->args.vc.actions_n) 9487 return -1; 9488 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 9489 /* Point to selected object. */ 9490 ctx->object = out->args.vc.data; 9491 ctx->objmask = NULL; 9492 /* Copy the headers to the buffer. */ 9493 action_encap_data = ctx->object; 9494 *action_encap_data = (struct action_raw_encap_data) { 9495 .conf = (struct rte_flow_action_raw_encap){ 9496 .data = action_encap_data->data, 9497 }, 9498 .data = {}, 9499 .preserve = {}, 9500 }; 9501 header = action_encap_data->data; 9502 if (mplsogre_encap_conf.select_vlan) 9503 eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 9504 else if (mplsogre_encap_conf.select_ipv4) 9505 eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 9506 else 9507 eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 9508 memcpy(eth.hdr.dst_addr.addr_bytes, 9509 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 9510 memcpy(eth.hdr.src_addr.addr_bytes, 9511 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 9512 memcpy(header, ð.hdr, sizeof(struct rte_ether_hdr)); 9513 header += sizeof(struct rte_ether_hdr); 9514 if (mplsogre_encap_conf.select_vlan) { 9515 if (mplsogre_encap_conf.select_ipv4) 9516 vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 9517 else 9518 vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 9519 memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr)); 9520 header += sizeof(struct rte_vlan_hdr); 9521 } 9522 if (mplsogre_encap_conf.select_ipv4) { 9523 memcpy(header, &ipv4, sizeof(ipv4)); 9524 header += sizeof(ipv4); 9525 } else { 9526 memcpy(&ipv6.hdr.src_addr, 9527 &mplsogre_encap_conf.ipv6_src, 9528 sizeof(mplsogre_encap_conf.ipv6_src)); 9529 memcpy(&ipv6.hdr.dst_addr, 9530 &mplsogre_encap_conf.ipv6_dst, 9531 sizeof(mplsogre_encap_conf.ipv6_dst)); 9532 memcpy(header, &ipv6, sizeof(ipv6)); 9533 header += sizeof(ipv6); 9534 } 9535 memcpy(header, &gre, sizeof(gre)); 9536 header += sizeof(gre); 9537 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label, 9538 RTE_DIM(mplsogre_encap_conf.label)); 9539 mpls.label_tc_s[2] |= 0x1; 9540 memcpy(header, &mpls, sizeof(mpls)); 9541 header += sizeof(mpls); 9542 action_encap_data->conf.size = header - 9543 action_encap_data->data; 9544 action->conf = &action_encap_data->conf; 9545 return ret; 9546 } 9547 9548 /** Parse MPLSOGRE decap action. */ 9549 static int 9550 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token, 9551 const char *str, unsigned int len, 9552 void *buf, unsigned int size) 9553 { 9554 struct buffer *out = buf; 9555 struct rte_flow_action *action; 9556 struct action_raw_decap_data *action_decap_data; 9557 struct rte_flow_item_eth eth = { .hdr.ether_type = 0, }; 9558 struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0}; 9559 struct rte_flow_item_ipv4 ipv4 = { 9560 .hdr = { 9561 .next_proto_id = IPPROTO_GRE, 9562 }, 9563 }; 9564 struct rte_flow_item_ipv6 ipv6 = { 9565 .hdr = { 9566 .proto = IPPROTO_GRE, 9567 }, 9568 }; 9569 struct rte_flow_item_gre gre = { 9570 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST), 9571 }; 9572 struct rte_flow_item_mpls mpls; 9573 uint8_t *header; 9574 int ret; 9575 9576 ret = parse_vc(ctx, token, str, len, buf, size); 9577 if (ret < 0) 9578 return ret; 9579 /* Nothing else to do if there is no buffer. */ 9580 if (!out) 9581 return ret; 9582 if (!out->args.vc.actions_n) 9583 return -1; 9584 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 9585 /* Point to selected object. */ 9586 ctx->object = out->args.vc.data; 9587 ctx->objmask = NULL; 9588 /* Copy the headers to the buffer. */ 9589 action_decap_data = ctx->object; 9590 *action_decap_data = (struct action_raw_decap_data) { 9591 .conf = (struct rte_flow_action_raw_decap){ 9592 .data = action_decap_data->data, 9593 }, 9594 .data = {}, 9595 }; 9596 header = action_decap_data->data; 9597 if (mplsogre_decap_conf.select_vlan) 9598 eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 9599 else if (mplsogre_encap_conf.select_ipv4) 9600 eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 9601 else 9602 eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 9603 memcpy(eth.hdr.dst_addr.addr_bytes, 9604 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 9605 memcpy(eth.hdr.src_addr.addr_bytes, 9606 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 9607 memcpy(header, ð.hdr, sizeof(struct rte_ether_hdr)); 9608 header += sizeof(struct rte_ether_hdr); 9609 if (mplsogre_encap_conf.select_vlan) { 9610 if (mplsogre_encap_conf.select_ipv4) 9611 vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 9612 else 9613 vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 9614 memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr)); 9615 header += sizeof(struct rte_vlan_hdr); 9616 } 9617 if (mplsogre_encap_conf.select_ipv4) { 9618 memcpy(header, &ipv4, sizeof(ipv4)); 9619 header += sizeof(ipv4); 9620 } else { 9621 memcpy(header, &ipv6, sizeof(ipv6)); 9622 header += sizeof(ipv6); 9623 } 9624 memcpy(header, &gre, sizeof(gre)); 9625 header += sizeof(gre); 9626 memset(&mpls, 0, sizeof(mpls)); 9627 memcpy(header, &mpls, sizeof(mpls)); 9628 header += sizeof(mpls); 9629 action_decap_data->conf.size = header - 9630 action_decap_data->data; 9631 action->conf = &action_decap_data->conf; 9632 return ret; 9633 } 9634 9635 /** Parse MPLSOUDP encap action. */ 9636 static int 9637 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token, 9638 const char *str, unsigned int len, 9639 void *buf, unsigned int size) 9640 { 9641 struct buffer *out = buf; 9642 struct rte_flow_action *action; 9643 struct action_raw_encap_data *action_encap_data; 9644 struct rte_flow_item_eth eth = { .hdr.ether_type = 0, }; 9645 struct rte_flow_item_vlan vlan = { 9646 .hdr.vlan_tci = mplsoudp_encap_conf.vlan_tci, 9647 .hdr.eth_proto = 0, 9648 }; 9649 struct rte_flow_item_ipv4 ipv4 = { 9650 .hdr = { 9651 .src_addr = mplsoudp_encap_conf.ipv4_src, 9652 .dst_addr = mplsoudp_encap_conf.ipv4_dst, 9653 .next_proto_id = IPPROTO_UDP, 9654 .version_ihl = RTE_IPV4_VHL_DEF, 9655 .time_to_live = IPDEFTTL, 9656 }, 9657 }; 9658 struct rte_flow_item_ipv6 ipv6 = { 9659 .hdr = { 9660 .proto = IPPROTO_UDP, 9661 .hop_limits = IPDEFTTL, 9662 }, 9663 }; 9664 struct rte_flow_item_udp udp = { 9665 .hdr = { 9666 .src_port = mplsoudp_encap_conf.udp_src, 9667 .dst_port = mplsoudp_encap_conf.udp_dst, 9668 }, 9669 }; 9670 struct rte_flow_item_mpls mpls; 9671 uint8_t *header; 9672 int ret; 9673 9674 ret = parse_vc(ctx, token, str, len, buf, size); 9675 if (ret < 0) 9676 return ret; 9677 /* Nothing else to do if there is no buffer. */ 9678 if (!out) 9679 return ret; 9680 if (!out->args.vc.actions_n) 9681 return -1; 9682 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 9683 /* Point to selected object. */ 9684 ctx->object = out->args.vc.data; 9685 ctx->objmask = NULL; 9686 /* Copy the headers to the buffer. */ 9687 action_encap_data = ctx->object; 9688 *action_encap_data = (struct action_raw_encap_data) { 9689 .conf = (struct rte_flow_action_raw_encap){ 9690 .data = action_encap_data->data, 9691 }, 9692 .data = {}, 9693 .preserve = {}, 9694 }; 9695 header = action_encap_data->data; 9696 if (mplsoudp_encap_conf.select_vlan) 9697 eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 9698 else if (mplsoudp_encap_conf.select_ipv4) 9699 eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 9700 else 9701 eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 9702 memcpy(eth.hdr.dst_addr.addr_bytes, 9703 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 9704 memcpy(eth.hdr.src_addr.addr_bytes, 9705 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 9706 memcpy(header, ð.hdr, sizeof(struct rte_ether_hdr)); 9707 header += sizeof(struct rte_ether_hdr); 9708 if (mplsoudp_encap_conf.select_vlan) { 9709 if (mplsoudp_encap_conf.select_ipv4) 9710 vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 9711 else 9712 vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 9713 memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr)); 9714 header += sizeof(struct rte_vlan_hdr); 9715 } 9716 if (mplsoudp_encap_conf.select_ipv4) { 9717 memcpy(header, &ipv4, sizeof(ipv4)); 9718 header += sizeof(ipv4); 9719 } else { 9720 memcpy(&ipv6.hdr.src_addr, 9721 &mplsoudp_encap_conf.ipv6_src, 9722 sizeof(mplsoudp_encap_conf.ipv6_src)); 9723 memcpy(&ipv6.hdr.dst_addr, 9724 &mplsoudp_encap_conf.ipv6_dst, 9725 sizeof(mplsoudp_encap_conf.ipv6_dst)); 9726 memcpy(header, &ipv6, sizeof(ipv6)); 9727 header += sizeof(ipv6); 9728 } 9729 memcpy(header, &udp, sizeof(udp)); 9730 header += sizeof(udp); 9731 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label, 9732 RTE_DIM(mplsoudp_encap_conf.label)); 9733 mpls.label_tc_s[2] |= 0x1; 9734 memcpy(header, &mpls, sizeof(mpls)); 9735 header += sizeof(mpls); 9736 action_encap_data->conf.size = header - 9737 action_encap_data->data; 9738 action->conf = &action_encap_data->conf; 9739 return ret; 9740 } 9741 9742 /** Parse MPLSOUDP decap action. */ 9743 static int 9744 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token, 9745 const char *str, unsigned int len, 9746 void *buf, unsigned int size) 9747 { 9748 struct buffer *out = buf; 9749 struct rte_flow_action *action; 9750 struct action_raw_decap_data *action_decap_data; 9751 struct rte_flow_item_eth eth = { .hdr.ether_type = 0, }; 9752 struct rte_flow_item_vlan vlan = {.hdr.vlan_tci = 0}; 9753 struct rte_flow_item_ipv4 ipv4 = { 9754 .hdr = { 9755 .next_proto_id = IPPROTO_UDP, 9756 }, 9757 }; 9758 struct rte_flow_item_ipv6 ipv6 = { 9759 .hdr = { 9760 .proto = IPPROTO_UDP, 9761 }, 9762 }; 9763 struct rte_flow_item_udp udp = { 9764 .hdr = { 9765 .dst_port = rte_cpu_to_be_16(6635), 9766 }, 9767 }; 9768 struct rte_flow_item_mpls mpls; 9769 uint8_t *header; 9770 int ret; 9771 9772 ret = parse_vc(ctx, token, str, len, buf, size); 9773 if (ret < 0) 9774 return ret; 9775 /* Nothing else to do if there is no buffer. */ 9776 if (!out) 9777 return ret; 9778 if (!out->args.vc.actions_n) 9779 return -1; 9780 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 9781 /* Point to selected object. */ 9782 ctx->object = out->args.vc.data; 9783 ctx->objmask = NULL; 9784 /* Copy the headers to the buffer. */ 9785 action_decap_data = ctx->object; 9786 *action_decap_data = (struct action_raw_decap_data) { 9787 .conf = (struct rte_flow_action_raw_decap){ 9788 .data = action_decap_data->data, 9789 }, 9790 .data = {}, 9791 }; 9792 header = action_decap_data->data; 9793 if (mplsoudp_decap_conf.select_vlan) 9794 eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 9795 else if (mplsoudp_encap_conf.select_ipv4) 9796 eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 9797 else 9798 eth.hdr.ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 9799 memcpy(eth.hdr.dst_addr.addr_bytes, 9800 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 9801 memcpy(eth.hdr.src_addr.addr_bytes, 9802 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 9803 memcpy(header, ð.hdr, sizeof(struct rte_ether_hdr)); 9804 header += sizeof(struct rte_ether_hdr); 9805 if (mplsoudp_encap_conf.select_vlan) { 9806 if (mplsoudp_encap_conf.select_ipv4) 9807 vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 9808 else 9809 vlan.hdr.eth_proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 9810 memcpy(header, &vlan.hdr, sizeof(struct rte_vlan_hdr)); 9811 header += sizeof(struct rte_vlan_hdr); 9812 } 9813 if (mplsoudp_encap_conf.select_ipv4) { 9814 memcpy(header, &ipv4, sizeof(ipv4)); 9815 header += sizeof(ipv4); 9816 } else { 9817 memcpy(header, &ipv6, sizeof(ipv6)); 9818 header += sizeof(ipv6); 9819 } 9820 memcpy(header, &udp, sizeof(udp)); 9821 header += sizeof(udp); 9822 memset(&mpls, 0, sizeof(mpls)); 9823 memcpy(header, &mpls, sizeof(mpls)); 9824 header += sizeof(mpls); 9825 action_decap_data->conf.size = header - 9826 action_decap_data->data; 9827 action->conf = &action_decap_data->conf; 9828 return ret; 9829 } 9830 9831 static int 9832 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token, 9833 const char *str, unsigned int len, void *buf, 9834 unsigned int size) 9835 { 9836 struct action_raw_decap_data *action_raw_decap_data; 9837 struct rte_flow_action *action; 9838 const struct arg *arg; 9839 struct buffer *out = buf; 9840 int ret; 9841 uint16_t idx; 9842 9843 RTE_SET_USED(token); 9844 RTE_SET_USED(buf); 9845 RTE_SET_USED(size); 9846 arg = ARGS_ENTRY_ARB_BOUNDED 9847 (offsetof(struct action_raw_decap_data, idx), 9848 sizeof(((struct action_raw_decap_data *)0)->idx), 9849 0, RAW_ENCAP_CONFS_MAX_NUM - 1); 9850 if (push_args(ctx, arg)) 9851 return -1; 9852 ret = parse_int(ctx, token, str, len, NULL, 0); 9853 if (ret < 0) { 9854 pop_args(ctx); 9855 return -1; 9856 } 9857 if (!ctx->object) 9858 return len; 9859 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 9860 action_raw_decap_data = ctx->object; 9861 idx = action_raw_decap_data->idx; 9862 action_raw_decap_data->conf.data = raw_decap_confs[idx].data; 9863 action_raw_decap_data->conf.size = raw_decap_confs[idx].size; 9864 action->conf = &action_raw_decap_data->conf; 9865 return len; 9866 } 9867 9868 9869 static int 9870 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token, 9871 const char *str, unsigned int len, void *buf, 9872 unsigned int size) 9873 { 9874 struct action_raw_encap_data *action_raw_encap_data; 9875 struct rte_flow_action *action; 9876 const struct arg *arg; 9877 struct buffer *out = buf; 9878 int ret; 9879 uint16_t idx; 9880 9881 RTE_SET_USED(token); 9882 RTE_SET_USED(buf); 9883 RTE_SET_USED(size); 9884 if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE) 9885 return -1; 9886 arg = ARGS_ENTRY_ARB_BOUNDED 9887 (offsetof(struct action_raw_encap_data, idx), 9888 sizeof(((struct action_raw_encap_data *)0)->idx), 9889 0, RAW_ENCAP_CONFS_MAX_NUM - 1); 9890 if (push_args(ctx, arg)) 9891 return -1; 9892 ret = parse_int(ctx, token, str, len, NULL, 0); 9893 if (ret < 0) { 9894 pop_args(ctx); 9895 return -1; 9896 } 9897 if (!ctx->object) 9898 return len; 9899 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 9900 action_raw_encap_data = ctx->object; 9901 idx = action_raw_encap_data->idx; 9902 action_raw_encap_data->conf.data = raw_encap_confs[idx].data; 9903 action_raw_encap_data->conf.size = raw_encap_confs[idx].size; 9904 action_raw_encap_data->conf.preserve = NULL; 9905 action->conf = &action_raw_encap_data->conf; 9906 return len; 9907 } 9908 9909 static int 9910 parse_vc_action_raw_encap(struct context *ctx, const struct token *token, 9911 const char *str, unsigned int len, void *buf, 9912 unsigned int size) 9913 { 9914 struct buffer *out = buf; 9915 int ret; 9916 9917 ret = parse_vc(ctx, token, str, len, buf, size); 9918 if (ret < 0) 9919 return ret; 9920 /* Nothing else to do if there is no buffer. */ 9921 if (!out) 9922 return ret; 9923 if (!out->args.vc.actions_n) 9924 return -1; 9925 /* Point to selected object. */ 9926 ctx->object = out->args.vc.data; 9927 ctx->objmask = NULL; 9928 return ret; 9929 } 9930 9931 static int 9932 parse_vc_action_raw_decap(struct context *ctx, const struct token *token, 9933 const char *str, unsigned int len, void *buf, 9934 unsigned int size) 9935 { 9936 struct buffer *out = buf; 9937 struct rte_flow_action *action; 9938 struct action_raw_decap_data *action_raw_decap_data = NULL; 9939 int ret; 9940 9941 ret = parse_vc(ctx, token, str, len, buf, size); 9942 if (ret < 0) 9943 return ret; 9944 /* Nothing else to do if there is no buffer. */ 9945 if (!out) 9946 return ret; 9947 if (!out->args.vc.actions_n) 9948 return -1; 9949 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 9950 /* Point to selected object. */ 9951 ctx->object = out->args.vc.data; 9952 ctx->objmask = NULL; 9953 /* Copy the headers to the buffer. */ 9954 action_raw_decap_data = ctx->object; 9955 action_raw_decap_data->conf.data = raw_decap_confs[0].data; 9956 action_raw_decap_data->conf.size = raw_decap_confs[0].size; 9957 action->conf = &action_raw_decap_data->conf; 9958 return ret; 9959 } 9960 9961 static int 9962 parse_vc_action_ipv6_ext_remove(struct context *ctx, const struct token *token, 9963 const char *str, unsigned int len, void *buf, 9964 unsigned int size) 9965 { 9966 struct buffer *out = buf; 9967 struct rte_flow_action *action; 9968 struct action_ipv6_ext_remove_data *ipv6_ext_remove_data = NULL; 9969 int ret; 9970 9971 ret = parse_vc(ctx, token, str, len, buf, size); 9972 if (ret < 0) 9973 return ret; 9974 /* Nothing else to do if there is no buffer. */ 9975 if (!out) 9976 return ret; 9977 if (!out->args.vc.actions_n) 9978 return -1; 9979 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 9980 /* Point to selected object. */ 9981 ctx->object = out->args.vc.data; 9982 ctx->objmask = NULL; 9983 /* Copy the headers to the buffer. */ 9984 ipv6_ext_remove_data = ctx->object; 9985 ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[0].type; 9986 action->conf = &ipv6_ext_remove_data->conf; 9987 return ret; 9988 } 9989 9990 static int 9991 parse_vc_action_ipv6_ext_remove_index(struct context *ctx, const struct token *token, 9992 const char *str, unsigned int len, void *buf, 9993 unsigned int size) 9994 { 9995 struct action_ipv6_ext_remove_data *action_ipv6_ext_remove_data; 9996 struct rte_flow_action *action; 9997 const struct arg *arg; 9998 struct buffer *out = buf; 9999 int ret; 10000 uint16_t idx; 10001 10002 RTE_SET_USED(token); 10003 RTE_SET_USED(buf); 10004 RTE_SET_USED(size); 10005 arg = ARGS_ENTRY_ARB_BOUNDED 10006 (offsetof(struct action_ipv6_ext_remove_data, idx), 10007 sizeof(((struct action_ipv6_ext_remove_data *)0)->idx), 10008 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1); 10009 if (push_args(ctx, arg)) 10010 return -1; 10011 ret = parse_int(ctx, token, str, len, NULL, 0); 10012 if (ret < 0) { 10013 pop_args(ctx); 10014 return -1; 10015 } 10016 if (!ctx->object) 10017 return len; 10018 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 10019 action_ipv6_ext_remove_data = ctx->object; 10020 idx = action_ipv6_ext_remove_data->idx; 10021 action_ipv6_ext_remove_data->conf.type = ipv6_ext_remove_confs[idx].type; 10022 action->conf = &action_ipv6_ext_remove_data->conf; 10023 return len; 10024 } 10025 10026 static int 10027 parse_vc_action_ipv6_ext_push(struct context *ctx, const struct token *token, 10028 const char *str, unsigned int len, void *buf, 10029 unsigned int size) 10030 { 10031 struct buffer *out = buf; 10032 struct rte_flow_action *action; 10033 struct action_ipv6_ext_push_data *ipv6_ext_push_data = NULL; 10034 int ret; 10035 10036 ret = parse_vc(ctx, token, str, len, buf, size); 10037 if (ret < 0) 10038 return ret; 10039 /* Nothing else to do if there is no buffer. */ 10040 if (!out) 10041 return ret; 10042 if (!out->args.vc.actions_n) 10043 return -1; 10044 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 10045 /* Point to selected object. */ 10046 ctx->object = out->args.vc.data; 10047 ctx->objmask = NULL; 10048 /* Copy the headers to the buffer. */ 10049 ipv6_ext_push_data = ctx->object; 10050 ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[0].type; 10051 ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[0].data; 10052 ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[0].size; 10053 action->conf = &ipv6_ext_push_data->conf; 10054 return ret; 10055 } 10056 10057 static int 10058 parse_vc_action_ipv6_ext_push_index(struct context *ctx, const struct token *token, 10059 const char *str, unsigned int len, void *buf, 10060 unsigned int size) 10061 { 10062 struct action_ipv6_ext_push_data *action_ipv6_ext_push_data; 10063 struct rte_flow_action *action; 10064 const struct arg *arg; 10065 struct buffer *out = buf; 10066 int ret; 10067 uint16_t idx; 10068 10069 RTE_SET_USED(token); 10070 RTE_SET_USED(buf); 10071 RTE_SET_USED(size); 10072 arg = ARGS_ENTRY_ARB_BOUNDED 10073 (offsetof(struct action_ipv6_ext_push_data, idx), 10074 sizeof(((struct action_ipv6_ext_push_data *)0)->idx), 10075 0, IPV6_EXT_PUSH_CONFS_MAX_NUM - 1); 10076 if (push_args(ctx, arg)) 10077 return -1; 10078 ret = parse_int(ctx, token, str, len, NULL, 0); 10079 if (ret < 0) { 10080 pop_args(ctx); 10081 return -1; 10082 } 10083 if (!ctx->object) 10084 return len; 10085 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 10086 action_ipv6_ext_push_data = ctx->object; 10087 idx = action_ipv6_ext_push_data->idx; 10088 action_ipv6_ext_push_data->conf.type = ipv6_ext_push_confs[idx].type; 10089 action_ipv6_ext_push_data->conf.size = ipv6_ext_push_confs[idx].size; 10090 action_ipv6_ext_push_data->conf.data = ipv6_ext_push_confs[idx].data; 10091 action->conf = &action_ipv6_ext_push_data->conf; 10092 return len; 10093 } 10094 10095 static int 10096 parse_vc_action_set_meta(struct context *ctx, const struct token *token, 10097 const char *str, unsigned int len, void *buf, 10098 unsigned int size) 10099 { 10100 int ret; 10101 10102 ret = parse_vc(ctx, token, str, len, buf, size); 10103 if (ret < 0) 10104 return ret; 10105 ret = rte_flow_dynf_metadata_register(); 10106 if (ret < 0) 10107 return -1; 10108 return len; 10109 } 10110 10111 static int 10112 parse_vc_action_sample(struct context *ctx, const struct token *token, 10113 const char *str, unsigned int len, void *buf, 10114 unsigned int size) 10115 { 10116 struct buffer *out = buf; 10117 struct rte_flow_action *action; 10118 struct action_sample_data *action_sample_data = NULL; 10119 static struct rte_flow_action end_action = { 10120 RTE_FLOW_ACTION_TYPE_END, 0 10121 }; 10122 int ret; 10123 10124 ret = parse_vc(ctx, token, str, len, buf, size); 10125 if (ret < 0) 10126 return ret; 10127 /* Nothing else to do if there is no buffer. */ 10128 if (!out) 10129 return ret; 10130 if (!out->args.vc.actions_n) 10131 return -1; 10132 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 10133 /* Point to selected object. */ 10134 ctx->object = out->args.vc.data; 10135 ctx->objmask = NULL; 10136 /* Copy the headers to the buffer. */ 10137 action_sample_data = ctx->object; 10138 action_sample_data->conf.actions = &end_action; 10139 action->conf = &action_sample_data->conf; 10140 return ret; 10141 } 10142 10143 static int 10144 parse_vc_action_sample_index(struct context *ctx, const struct token *token, 10145 const char *str, unsigned int len, void *buf, 10146 unsigned int size) 10147 { 10148 struct action_sample_data *action_sample_data; 10149 struct rte_flow_action *action; 10150 const struct arg *arg; 10151 struct buffer *out = buf; 10152 int ret; 10153 uint16_t idx; 10154 10155 RTE_SET_USED(token); 10156 RTE_SET_USED(buf); 10157 RTE_SET_USED(size); 10158 if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE) 10159 return -1; 10160 arg = ARGS_ENTRY_ARB_BOUNDED 10161 (offsetof(struct action_sample_data, idx), 10162 sizeof(((struct action_sample_data *)0)->idx), 10163 0, RAW_SAMPLE_CONFS_MAX_NUM - 1); 10164 if (push_args(ctx, arg)) 10165 return -1; 10166 ret = parse_int(ctx, token, str, len, NULL, 0); 10167 if (ret < 0) { 10168 pop_args(ctx); 10169 return -1; 10170 } 10171 if (!ctx->object) 10172 return len; 10173 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 10174 action_sample_data = ctx->object; 10175 idx = action_sample_data->idx; 10176 action_sample_data->conf.actions = raw_sample_confs[idx].data; 10177 action->conf = &action_sample_data->conf; 10178 return len; 10179 } 10180 10181 /** Parse operation for modify_field command. */ 10182 static int 10183 parse_vc_modify_field_op(struct context *ctx, const struct token *token, 10184 const char *str, unsigned int len, void *buf, 10185 unsigned int size) 10186 { 10187 struct rte_flow_action_modify_field *action_modify_field; 10188 unsigned int i; 10189 10190 (void)token; 10191 (void)buf; 10192 (void)size; 10193 if (ctx->curr != ACTION_MODIFY_FIELD_OP_VALUE) 10194 return -1; 10195 for (i = 0; modify_field_ops[i]; ++i) 10196 if (!strcmp_partial(modify_field_ops[i], str, len)) 10197 break; 10198 if (!modify_field_ops[i]) 10199 return -1; 10200 if (!ctx->object) 10201 return len; 10202 action_modify_field = ctx->object; 10203 action_modify_field->operation = (enum rte_flow_modify_op)i; 10204 return len; 10205 } 10206 10207 /** Parse id for modify_field command. */ 10208 static int 10209 parse_vc_modify_field_id(struct context *ctx, const struct token *token, 10210 const char *str, unsigned int len, void *buf, 10211 unsigned int size) 10212 { 10213 struct rte_flow_action_modify_field *action_modify_field; 10214 unsigned int i; 10215 10216 (void)token; 10217 (void)buf; 10218 (void)size; 10219 if (ctx->curr != ACTION_MODIFY_FIELD_DST_TYPE_VALUE && 10220 ctx->curr != ACTION_MODIFY_FIELD_SRC_TYPE_VALUE) 10221 return -1; 10222 for (i = 0; flow_field_ids[i]; ++i) 10223 if (!strcmp_partial(flow_field_ids[i], str, len)) 10224 break; 10225 if (!flow_field_ids[i]) 10226 return -1; 10227 if (!ctx->object) 10228 return len; 10229 action_modify_field = ctx->object; 10230 if (ctx->curr == ACTION_MODIFY_FIELD_DST_TYPE_VALUE) 10231 action_modify_field->dst.field = (enum rte_flow_field_id)i; 10232 else 10233 action_modify_field->src.field = (enum rte_flow_field_id)i; 10234 return len; 10235 } 10236 10237 /** Parse level for modify_field command. */ 10238 static int 10239 parse_vc_modify_field_level(struct context *ctx, const struct token *token, 10240 const char *str, unsigned int len, void *buf, 10241 unsigned int size) 10242 { 10243 struct rte_flow_action_modify_field *action; 10244 struct flex_item *fp = NULL; 10245 uint32_t val; 10246 struct buffer *out = buf; 10247 char *end; 10248 10249 (void)token; 10250 (void)size; 10251 if (ctx->curr != ACTION_MODIFY_FIELD_DST_LEVEL_VALUE && 10252 ctx->curr != ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE) 10253 return -1; 10254 if (!ctx->object) 10255 return len; 10256 action = ctx->object; 10257 errno = 0; 10258 val = strtoumax(str, &end, 0); 10259 if (errno || (size_t)(end - str) != len) 10260 return -1; 10261 /* No need to validate action template mask value */ 10262 if (out->args.vc.masks) { 10263 if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE) 10264 action->dst.level = val; 10265 else 10266 action->src.level = val; 10267 return len; 10268 } 10269 if ((ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE && 10270 action->dst.field == RTE_FLOW_FIELD_FLEX_ITEM) || 10271 (ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE && 10272 action->src.field == RTE_FLOW_FIELD_FLEX_ITEM)) { 10273 if (val >= FLEX_MAX_PARSERS_NUM) { 10274 printf("Bad flex item handle\n"); 10275 return -1; 10276 } 10277 fp = flex_items[ctx->port][val]; 10278 if (!fp) { 10279 printf("Bad flex item handle\n"); 10280 return -1; 10281 } 10282 } 10283 if (ctx->curr == ACTION_MODIFY_FIELD_DST_LEVEL_VALUE) { 10284 if (action->dst.field != RTE_FLOW_FIELD_FLEX_ITEM) 10285 action->dst.level = val; 10286 else 10287 action->dst.flex_handle = fp->flex_handle; 10288 } else if (ctx->curr == ACTION_MODIFY_FIELD_SRC_LEVEL_VALUE) { 10289 if (action->src.field != RTE_FLOW_FIELD_FLEX_ITEM) 10290 action->src.level = val; 10291 else 10292 action->src.flex_handle = fp->flex_handle; 10293 } 10294 return len; 10295 } 10296 10297 /** Parse the conntrack update, not a rte_flow_action. */ 10298 static int 10299 parse_vc_action_conntrack_update(struct context *ctx, const struct token *token, 10300 const char *str, unsigned int len, void *buf, 10301 unsigned int size) 10302 { 10303 struct buffer *out = buf; 10304 struct rte_flow_modify_conntrack *ct_modify = NULL; 10305 10306 (void)size; 10307 if (ctx->curr != ACTION_CONNTRACK_UPDATE_CTX && 10308 ctx->curr != ACTION_CONNTRACK_UPDATE_DIR) 10309 return -1; 10310 /* Token name must match. */ 10311 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 10312 return -1; 10313 /* Nothing else to do if there is no buffer. */ 10314 if (!out) 10315 return len; 10316 ct_modify = (struct rte_flow_modify_conntrack *)out->args.vc.data; 10317 if (ctx->curr == ACTION_CONNTRACK_UPDATE_DIR) { 10318 ct_modify->new_ct.is_original_dir = 10319 conntrack_context.is_original_dir; 10320 ct_modify->direction = 1; 10321 } else { 10322 uint32_t old_dir; 10323 10324 old_dir = ct_modify->new_ct.is_original_dir; 10325 memcpy(&ct_modify->new_ct, &conntrack_context, 10326 sizeof(conntrack_context)); 10327 ct_modify->new_ct.is_original_dir = old_dir; 10328 ct_modify->state = 1; 10329 } 10330 return len; 10331 } 10332 10333 /** Parse tokens for destroy command. */ 10334 static int 10335 parse_destroy(struct context *ctx, const struct token *token, 10336 const char *str, unsigned int len, 10337 void *buf, unsigned int size) 10338 { 10339 struct buffer *out = buf; 10340 10341 /* Token name must match. */ 10342 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 10343 return -1; 10344 /* Nothing else to do if there is no buffer. */ 10345 if (!out) 10346 return len; 10347 if (!out->command) { 10348 if (ctx->curr != DESTROY) 10349 return -1; 10350 if (sizeof(*out) > size) 10351 return -1; 10352 out->command = ctx->curr; 10353 ctx->objdata = 0; 10354 ctx->object = out; 10355 ctx->objmask = NULL; 10356 out->args.destroy.rule = 10357 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 10358 sizeof(double)); 10359 return len; 10360 } 10361 if (ctx->curr == DESTROY_IS_USER_ID) { 10362 out->args.destroy.is_user_id = true; 10363 return len; 10364 } 10365 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) + 10366 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size) 10367 return -1; 10368 ctx->objdata = 0; 10369 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++; 10370 ctx->objmask = NULL; 10371 return len; 10372 } 10373 10374 /** Parse tokens for flush command. */ 10375 static int 10376 parse_flush(struct context *ctx, const struct token *token, 10377 const char *str, unsigned int len, 10378 void *buf, unsigned int size) 10379 { 10380 struct buffer *out = buf; 10381 10382 /* Token name must match. */ 10383 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 10384 return -1; 10385 /* Nothing else to do if there is no buffer. */ 10386 if (!out) 10387 return len; 10388 if (!out->command) { 10389 if (ctx->curr != FLUSH) 10390 return -1; 10391 if (sizeof(*out) > size) 10392 return -1; 10393 out->command = ctx->curr; 10394 ctx->objdata = 0; 10395 ctx->object = out; 10396 ctx->objmask = NULL; 10397 } 10398 return len; 10399 } 10400 10401 /** Parse tokens for dump command. */ 10402 static int 10403 parse_dump(struct context *ctx, const struct token *token, 10404 const char *str, unsigned int len, 10405 void *buf, unsigned int size) 10406 { 10407 struct buffer *out = buf; 10408 10409 /* Token name must match. */ 10410 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 10411 return -1; 10412 /* Nothing else to do if there is no buffer. */ 10413 if (!out) 10414 return len; 10415 if (!out->command) { 10416 if (ctx->curr != DUMP) 10417 return -1; 10418 if (sizeof(*out) > size) 10419 return -1; 10420 out->command = ctx->curr; 10421 ctx->objdata = 0; 10422 ctx->object = out; 10423 ctx->objmask = NULL; 10424 return len; 10425 } 10426 switch (ctx->curr) { 10427 case DUMP_ALL: 10428 case DUMP_ONE: 10429 out->args.dump.mode = (ctx->curr == DUMP_ALL) ? true : false; 10430 out->command = ctx->curr; 10431 ctx->objdata = 0; 10432 ctx->object = out; 10433 ctx->objmask = NULL; 10434 return len; 10435 case DUMP_IS_USER_ID: 10436 out->args.dump.is_user_id = true; 10437 return len; 10438 default: 10439 return -1; 10440 } 10441 } 10442 10443 /** Parse tokens for query command. */ 10444 static int 10445 parse_query(struct context *ctx, const struct token *token, 10446 const char *str, unsigned int len, 10447 void *buf, unsigned int size) 10448 { 10449 struct buffer *out = buf; 10450 10451 /* Token name must match. */ 10452 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 10453 return -1; 10454 /* Nothing else to do if there is no buffer. */ 10455 if (!out) 10456 return len; 10457 if (!out->command) { 10458 if (ctx->curr != QUERY) 10459 return -1; 10460 if (sizeof(*out) > size) 10461 return -1; 10462 out->command = ctx->curr; 10463 ctx->objdata = 0; 10464 ctx->object = out; 10465 ctx->objmask = NULL; 10466 } 10467 if (ctx->curr == QUERY_IS_USER_ID) { 10468 out->args.query.is_user_id = true; 10469 return len; 10470 } 10471 return len; 10472 } 10473 10474 /** Parse action names. */ 10475 static int 10476 parse_action(struct context *ctx, const struct token *token, 10477 const char *str, unsigned int len, 10478 void *buf, unsigned int size) 10479 { 10480 struct buffer *out = buf; 10481 const struct arg *arg = pop_args(ctx); 10482 unsigned int i; 10483 10484 (void)size; 10485 /* Argument is expected. */ 10486 if (!arg) 10487 return -1; 10488 /* Parse action name. */ 10489 for (i = 0; next_action[i]; ++i) { 10490 const struct parse_action_priv *priv; 10491 10492 token = &token_list[next_action[i]]; 10493 if (strcmp_partial(token->name, str, len)) 10494 continue; 10495 priv = token->priv; 10496 if (!priv) 10497 goto error; 10498 if (out) 10499 memcpy((uint8_t *)ctx->object + arg->offset, 10500 &priv->type, 10501 arg->size); 10502 return len; 10503 } 10504 error: 10505 push_args(ctx, arg); 10506 return -1; 10507 } 10508 10509 /** Parse tokens for list command. */ 10510 static int 10511 parse_list(struct context *ctx, const struct token *token, 10512 const char *str, unsigned int len, 10513 void *buf, unsigned int size) 10514 { 10515 struct buffer *out = buf; 10516 10517 /* Token name must match. */ 10518 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 10519 return -1; 10520 /* Nothing else to do if there is no buffer. */ 10521 if (!out) 10522 return len; 10523 if (!out->command) { 10524 if (ctx->curr != LIST) 10525 return -1; 10526 if (sizeof(*out) > size) 10527 return -1; 10528 out->command = ctx->curr; 10529 ctx->objdata = 0; 10530 ctx->object = out; 10531 ctx->objmask = NULL; 10532 out->args.list.group = 10533 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 10534 sizeof(double)); 10535 return len; 10536 } 10537 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) + 10538 sizeof(*out->args.list.group)) > (uint8_t *)out + size) 10539 return -1; 10540 ctx->objdata = 0; 10541 ctx->object = out->args.list.group + out->args.list.group_n++; 10542 ctx->objmask = NULL; 10543 return len; 10544 } 10545 10546 /** Parse tokens for list all aged flows command. */ 10547 static int 10548 parse_aged(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 || out->command == QUEUE) { 10561 if (ctx->curr != AGED && ctx->curr != QUEUE_AGED) 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 } 10570 if (ctx->curr == AGED_DESTROY) 10571 out->args.aged.destroy = 1; 10572 return len; 10573 } 10574 10575 /** Parse tokens for isolate command. */ 10576 static int 10577 parse_isolate(struct context *ctx, const struct token *token, 10578 const char *str, unsigned int len, 10579 void *buf, unsigned int size) 10580 { 10581 struct buffer *out = buf; 10582 10583 /* Token name must match. */ 10584 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 10585 return -1; 10586 /* Nothing else to do if there is no buffer. */ 10587 if (!out) 10588 return len; 10589 if (!out->command) { 10590 if (ctx->curr != ISOLATE) 10591 return -1; 10592 if (sizeof(*out) > size) 10593 return -1; 10594 out->command = ctx->curr; 10595 ctx->objdata = 0; 10596 ctx->object = out; 10597 ctx->objmask = NULL; 10598 } 10599 return len; 10600 } 10601 10602 /** Parse tokens for info/configure command. */ 10603 static int 10604 parse_configure(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 != INFO && ctx->curr != CONFIGURE) 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 } 10626 return len; 10627 } 10628 10629 /** Parse tokens for template create command. */ 10630 static int 10631 parse_template(struct context *ctx, const struct token *token, 10632 const char *str, unsigned int len, 10633 void *buf, unsigned int size) 10634 { 10635 struct buffer *out = buf; 10636 10637 /* Token name must match. */ 10638 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 10639 return -1; 10640 /* Nothing else to do if there is no buffer. */ 10641 if (!out) 10642 return len; 10643 if (!out->command) { 10644 if (ctx->curr != PATTERN_TEMPLATE && 10645 ctx->curr != ACTIONS_TEMPLATE) 10646 return -1; 10647 if (sizeof(*out) > size) 10648 return -1; 10649 out->command = ctx->curr; 10650 ctx->objdata = 0; 10651 ctx->object = out; 10652 ctx->objmask = NULL; 10653 out->args.vc.data = (uint8_t *)out + size; 10654 return len; 10655 } 10656 switch (ctx->curr) { 10657 case PATTERN_TEMPLATE_CREATE: 10658 out->args.vc.pattern = 10659 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 10660 sizeof(double)); 10661 out->args.vc.pat_templ_id = UINT32_MAX; 10662 out->command = ctx->curr; 10663 ctx->objdata = 0; 10664 ctx->object = out; 10665 ctx->objmask = NULL; 10666 return len; 10667 case PATTERN_TEMPLATE_EGRESS: 10668 out->args.vc.attr.egress = 1; 10669 return len; 10670 case PATTERN_TEMPLATE_INGRESS: 10671 out->args.vc.attr.ingress = 1; 10672 return len; 10673 case PATTERN_TEMPLATE_TRANSFER: 10674 out->args.vc.attr.transfer = 1; 10675 return len; 10676 case ACTIONS_TEMPLATE_CREATE: 10677 out->args.vc.act_templ_id = UINT32_MAX; 10678 out->command = ctx->curr; 10679 ctx->objdata = 0; 10680 ctx->object = out; 10681 ctx->objmask = NULL; 10682 return len; 10683 case ACTIONS_TEMPLATE_SPEC: 10684 out->args.vc.actions = 10685 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 10686 sizeof(double)); 10687 ctx->object = out->args.vc.actions; 10688 ctx->objmask = NULL; 10689 return len; 10690 case ACTIONS_TEMPLATE_MASK: 10691 out->args.vc.masks = 10692 (void *)RTE_ALIGN_CEIL((uintptr_t) 10693 (out->args.vc.actions + 10694 out->args.vc.actions_n), 10695 sizeof(double)); 10696 ctx->object = out->args.vc.masks; 10697 ctx->objmask = NULL; 10698 return len; 10699 case ACTIONS_TEMPLATE_EGRESS: 10700 out->args.vc.attr.egress = 1; 10701 return len; 10702 case ACTIONS_TEMPLATE_INGRESS: 10703 out->args.vc.attr.ingress = 1; 10704 return len; 10705 case ACTIONS_TEMPLATE_TRANSFER: 10706 out->args.vc.attr.transfer = 1; 10707 return len; 10708 default: 10709 return -1; 10710 } 10711 } 10712 10713 /** Parse tokens for template destroy command. */ 10714 static int 10715 parse_template_destroy(struct context *ctx, const struct token *token, 10716 const char *str, unsigned int len, 10717 void *buf, unsigned int size) 10718 { 10719 struct buffer *out = buf; 10720 uint32_t *template_id; 10721 10722 /* Token name must match. */ 10723 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 10724 return -1; 10725 /* Nothing else to do if there is no buffer. */ 10726 if (!out) 10727 return len; 10728 if (!out->command || 10729 out->command == PATTERN_TEMPLATE || 10730 out->command == ACTIONS_TEMPLATE) { 10731 if (ctx->curr != PATTERN_TEMPLATE_DESTROY && 10732 ctx->curr != ACTIONS_TEMPLATE_DESTROY) 10733 return -1; 10734 if (sizeof(*out) > size) 10735 return -1; 10736 out->command = ctx->curr; 10737 ctx->objdata = 0; 10738 ctx->object = out; 10739 ctx->objmask = NULL; 10740 out->args.templ_destroy.template_id = 10741 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 10742 sizeof(double)); 10743 return len; 10744 } 10745 template_id = out->args.templ_destroy.template_id 10746 + out->args.templ_destroy.template_id_n++; 10747 if ((uint8_t *)template_id > (uint8_t *)out + size) 10748 return -1; 10749 ctx->objdata = 0; 10750 ctx->object = template_id; 10751 ctx->objmask = NULL; 10752 return len; 10753 } 10754 10755 /** Parse tokens for table create command. */ 10756 static int 10757 parse_table(struct context *ctx, const struct token *token, 10758 const char *str, unsigned int len, 10759 void *buf, unsigned int size) 10760 { 10761 struct buffer *out = buf; 10762 uint32_t *template_id; 10763 10764 /* Token name must match. */ 10765 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 10766 return -1; 10767 /* Nothing else to do if there is no buffer. */ 10768 if (!out) 10769 return len; 10770 if (!out->command) { 10771 if (ctx->curr != TABLE) 10772 return -1; 10773 if (sizeof(*out) > size) 10774 return -1; 10775 out->command = ctx->curr; 10776 ctx->objdata = 0; 10777 ctx->object = out; 10778 ctx->objmask = NULL; 10779 return len; 10780 } 10781 switch (ctx->curr) { 10782 case TABLE_CREATE: 10783 out->command = ctx->curr; 10784 ctx->objdata = 0; 10785 ctx->object = out; 10786 ctx->objmask = NULL; 10787 out->args.table.id = UINT32_MAX; 10788 return len; 10789 case TABLE_PATTERN_TEMPLATE: 10790 out->args.table.pat_templ_id = 10791 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 10792 sizeof(double)); 10793 template_id = out->args.table.pat_templ_id 10794 + out->args.table.pat_templ_id_n++; 10795 if ((uint8_t *)template_id > (uint8_t *)out + size) 10796 return -1; 10797 ctx->objdata = 0; 10798 ctx->object = template_id; 10799 ctx->objmask = NULL; 10800 return len; 10801 case TABLE_ACTIONS_TEMPLATE: 10802 out->args.table.act_templ_id = 10803 (void *)RTE_ALIGN_CEIL((uintptr_t) 10804 (out->args.table.pat_templ_id + 10805 out->args.table.pat_templ_id_n), 10806 sizeof(double)); 10807 template_id = out->args.table.act_templ_id 10808 + out->args.table.act_templ_id_n++; 10809 if ((uint8_t *)template_id > (uint8_t *)out + size) 10810 return -1; 10811 ctx->objdata = 0; 10812 ctx->object = template_id; 10813 ctx->objmask = NULL; 10814 return len; 10815 case TABLE_INGRESS: 10816 out->args.table.attr.flow_attr.ingress = 1; 10817 return len; 10818 case TABLE_EGRESS: 10819 out->args.table.attr.flow_attr.egress = 1; 10820 return len; 10821 case TABLE_TRANSFER: 10822 out->args.table.attr.flow_attr.transfer = 1; 10823 return len; 10824 case TABLE_TRANSFER_WIRE_ORIG: 10825 if (!out->args.table.attr.flow_attr.transfer) 10826 return -1; 10827 out->args.table.attr.specialize = RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_WIRE_ORIG; 10828 return len; 10829 case TABLE_TRANSFER_VPORT_ORIG: 10830 if (!out->args.table.attr.flow_attr.transfer) 10831 return -1; 10832 out->args.table.attr.specialize = RTE_FLOW_TABLE_SPECIALIZE_TRANSFER_VPORT_ORIG; 10833 return len; 10834 case TABLE_RULES_NUMBER: 10835 ctx->objdata = 0; 10836 ctx->object = out; 10837 ctx->objmask = NULL; 10838 return len; 10839 default: 10840 return -1; 10841 } 10842 } 10843 10844 /** Parse tokens for table destroy command. */ 10845 static int 10846 parse_table_destroy(struct context *ctx, const struct token *token, 10847 const char *str, unsigned int len, 10848 void *buf, unsigned int size) 10849 { 10850 struct buffer *out = buf; 10851 uint32_t *table_id; 10852 10853 /* Token name must match. */ 10854 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 10855 return -1; 10856 /* Nothing else to do if there is no buffer. */ 10857 if (!out) 10858 return len; 10859 if (!out->command || out->command == TABLE) { 10860 if (ctx->curr != TABLE_DESTROY) 10861 return -1; 10862 if (sizeof(*out) > size) 10863 return -1; 10864 out->command = ctx->curr; 10865 ctx->objdata = 0; 10866 ctx->object = out; 10867 ctx->objmask = NULL; 10868 out->args.table_destroy.table_id = 10869 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 10870 sizeof(double)); 10871 return len; 10872 } 10873 table_id = out->args.table_destroy.table_id 10874 + out->args.table_destroy.table_id_n++; 10875 if ((uint8_t *)table_id > (uint8_t *)out + size) 10876 return -1; 10877 ctx->objdata = 0; 10878 ctx->object = table_id; 10879 ctx->objmask = NULL; 10880 return len; 10881 } 10882 10883 /** Parse tokens for queue create commands. */ 10884 static int 10885 parse_qo(struct context *ctx, const struct token *token, 10886 const char *str, unsigned int len, 10887 void *buf, unsigned int size) 10888 { 10889 struct buffer *out = buf; 10890 10891 /* Token name must match. */ 10892 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 10893 return -1; 10894 /* Nothing else to do if there is no buffer. */ 10895 if (!out) 10896 return len; 10897 if (!out->command) { 10898 if (ctx->curr != QUEUE) 10899 return -1; 10900 if (sizeof(*out) > size) 10901 return -1; 10902 out->command = ctx->curr; 10903 ctx->objdata = 0; 10904 ctx->object = out; 10905 ctx->objmask = NULL; 10906 out->args.vc.data = (uint8_t *)out + size; 10907 return len; 10908 } 10909 switch (ctx->curr) { 10910 case QUEUE_CREATE: 10911 case QUEUE_UPDATE: 10912 out->command = ctx->curr; 10913 ctx->objdata = 0; 10914 ctx->object = out; 10915 ctx->objmask = NULL; 10916 out->args.vc.rule_id = UINT32_MAX; 10917 return len; 10918 case QUEUE_TEMPLATE_TABLE: 10919 case QUEUE_PATTERN_TEMPLATE: 10920 case QUEUE_ACTIONS_TEMPLATE: 10921 case QUEUE_CREATE_POSTPONE: 10922 case QUEUE_RULE_ID: 10923 case QUEUE_UPDATE_ID: 10924 return len; 10925 case ITEM_PATTERN: 10926 out->args.vc.pattern = 10927 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 10928 sizeof(double)); 10929 ctx->object = out->args.vc.pattern; 10930 ctx->objmask = NULL; 10931 return len; 10932 case ACTIONS: 10933 out->args.vc.actions = 10934 (void *)RTE_ALIGN_CEIL((uintptr_t) 10935 (out->args.vc.pattern + 10936 out->args.vc.pattern_n), 10937 sizeof(double)); 10938 ctx->object = out->args.vc.actions; 10939 ctx->objmask = NULL; 10940 return len; 10941 default: 10942 return -1; 10943 } 10944 } 10945 10946 /** Parse tokens for queue destroy command. */ 10947 static int 10948 parse_qo_destroy(struct context *ctx, const struct token *token, 10949 const char *str, unsigned int len, 10950 void *buf, unsigned int size) 10951 { 10952 struct buffer *out = buf; 10953 uint64_t *flow_id; 10954 10955 /* Token name must match. */ 10956 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 10957 return -1; 10958 /* Nothing else to do if there is no buffer. */ 10959 if (!out) 10960 return len; 10961 if (!out->command || out->command == QUEUE) { 10962 if (ctx->curr != QUEUE_DESTROY) 10963 return -1; 10964 if (sizeof(*out) > size) 10965 return -1; 10966 out->command = ctx->curr; 10967 ctx->objdata = 0; 10968 ctx->object = out; 10969 ctx->objmask = NULL; 10970 out->args.destroy.rule = 10971 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 10972 sizeof(double)); 10973 return len; 10974 } 10975 switch (ctx->curr) { 10976 case QUEUE_DESTROY_ID: 10977 flow_id = out->args.destroy.rule 10978 + out->args.destroy.rule_n++; 10979 if ((uint8_t *)flow_id > (uint8_t *)out + size) 10980 return -1; 10981 ctx->objdata = 0; 10982 ctx->object = flow_id; 10983 ctx->objmask = NULL; 10984 return len; 10985 case QUEUE_DESTROY_POSTPONE: 10986 return len; 10987 default: 10988 return -1; 10989 } 10990 } 10991 10992 /** Parse tokens for push queue command. */ 10993 static int 10994 parse_push(struct context *ctx, const struct token *token, 10995 const char *str, unsigned int len, 10996 void *buf, unsigned int size) 10997 { 10998 struct buffer *out = buf; 10999 11000 /* Token name must match. */ 11001 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 11002 return -1; 11003 /* Nothing else to do if there is no buffer. */ 11004 if (!out) 11005 return len; 11006 if (!out->command) { 11007 if (ctx->curr != PUSH) 11008 return -1; 11009 if (sizeof(*out) > size) 11010 return -1; 11011 out->command = ctx->curr; 11012 ctx->objdata = 0; 11013 ctx->object = out; 11014 ctx->objmask = NULL; 11015 out->args.vc.data = (uint8_t *)out + size; 11016 } 11017 return len; 11018 } 11019 11020 /** Parse tokens for pull command. */ 11021 static int 11022 parse_pull(struct context *ctx, const struct token *token, 11023 const char *str, unsigned int len, 11024 void *buf, unsigned int size) 11025 { 11026 struct buffer *out = buf; 11027 11028 /* Token name must match. */ 11029 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 11030 return -1; 11031 /* Nothing else to do if there is no buffer. */ 11032 if (!out) 11033 return len; 11034 if (!out->command) { 11035 if (ctx->curr != PULL) 11036 return -1; 11037 if (sizeof(*out) > size) 11038 return -1; 11039 out->command = ctx->curr; 11040 ctx->objdata = 0; 11041 ctx->object = out; 11042 ctx->objmask = NULL; 11043 out->args.vc.data = (uint8_t *)out + size; 11044 } 11045 return len; 11046 } 11047 11048 /** Parse tokens for hash calculation commands. */ 11049 static int 11050 parse_hash(struct context *ctx, const struct token *token, 11051 const char *str, unsigned int len, 11052 void *buf, unsigned int size) 11053 { 11054 struct buffer *out = buf; 11055 11056 /* Token name must match. */ 11057 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 11058 return -1; 11059 /* Nothing else to do if there is no buffer. */ 11060 if (!out) 11061 return len; 11062 if (!out->command) { 11063 if (ctx->curr != HASH) 11064 return -1; 11065 if (sizeof(*out) > size) 11066 return -1; 11067 out->command = ctx->curr; 11068 ctx->objdata = 0; 11069 ctx->object = out; 11070 ctx->objmask = NULL; 11071 out->args.vc.data = (uint8_t *)out + size; 11072 return len; 11073 } 11074 switch (ctx->curr) { 11075 case HASH_CALC_TABLE: 11076 case HASH_CALC_PATTERN_INDEX: 11077 return len; 11078 case ITEM_PATTERN: 11079 out->args.vc.pattern = 11080 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 11081 sizeof(double)); 11082 ctx->object = out->args.vc.pattern; 11083 ctx->objmask = NULL; 11084 return len; 11085 case HASH_CALC_ENCAP: 11086 out->args.vc.encap_hash = 1; 11087 return len; 11088 case ENCAP_HASH_FIELD_SRC_PORT: 11089 out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT; 11090 return len; 11091 case ENCAP_HASH_FIELD_GRE_FLOW_ID: 11092 out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID; 11093 return len; 11094 default: 11095 return -1; 11096 } 11097 } 11098 11099 static int 11100 parse_group(struct context *ctx, const struct token *token, 11101 const char *str, unsigned int len, 11102 void *buf, unsigned int size) 11103 { 11104 struct buffer *out = buf; 11105 11106 /* Token name must match. */ 11107 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 11108 return -1; 11109 /* Nothing else to do if there is no buffer. */ 11110 if (!out) 11111 return len; 11112 if (!out->command) { 11113 if (ctx->curr != FLOW_GROUP) 11114 return -1; 11115 if (sizeof(*out) > size) 11116 return -1; 11117 out->command = ctx->curr; 11118 ctx->objdata = 0; 11119 ctx->object = out; 11120 ctx->objmask = NULL; 11121 out->args.vc.data = (uint8_t *)out + size; 11122 return len; 11123 } 11124 switch (ctx->curr) { 11125 case GROUP_INGRESS: 11126 out->args.vc.attr.ingress = 1; 11127 return len; 11128 case GROUP_EGRESS: 11129 out->args.vc.attr.egress = 1; 11130 return len; 11131 case GROUP_TRANSFER: 11132 out->args.vc.attr.transfer = 1; 11133 return len; 11134 case GROUP_SET_MISS_ACTIONS: 11135 out->command = ctx->curr; 11136 ctx->objdata = 0; 11137 ctx->object = out; 11138 ctx->objmask = NULL; 11139 out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 11140 sizeof(double)); 11141 return len; 11142 default: 11143 return -1; 11144 } 11145 } 11146 11147 static int 11148 parse_flex(struct context *ctx, const struct token *token, 11149 const char *str, unsigned int len, 11150 void *buf, unsigned int size) 11151 { 11152 struct buffer *out = buf; 11153 11154 /* Token name must match. */ 11155 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 11156 return -1; 11157 /* Nothing else to do if there is no buffer. */ 11158 if (!out) 11159 return len; 11160 if (out->command == ZERO) { 11161 if (ctx->curr != FLEX) 11162 return -1; 11163 if (sizeof(*out) > size) 11164 return -1; 11165 out->command = ctx->curr; 11166 ctx->objdata = 0; 11167 ctx->object = out; 11168 ctx->objmask = NULL; 11169 } else { 11170 switch (ctx->curr) { 11171 default: 11172 break; 11173 case FLEX_ITEM_INIT: 11174 case FLEX_ITEM_CREATE: 11175 case FLEX_ITEM_DESTROY: 11176 out->command = ctx->curr; 11177 break; 11178 } 11179 } 11180 11181 return len; 11182 } 11183 11184 static int 11185 parse_tunnel(struct context *ctx, const struct token *token, 11186 const char *str, unsigned int len, 11187 void *buf, unsigned int size) 11188 { 11189 struct buffer *out = buf; 11190 11191 /* Token name must match. */ 11192 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 11193 return -1; 11194 /* Nothing else to do if there is no buffer. */ 11195 if (!out) 11196 return len; 11197 if (!out->command) { 11198 if (ctx->curr != TUNNEL) 11199 return -1; 11200 if (sizeof(*out) > size) 11201 return -1; 11202 out->command = ctx->curr; 11203 ctx->objdata = 0; 11204 ctx->object = out; 11205 ctx->objmask = NULL; 11206 } else { 11207 switch (ctx->curr) { 11208 default: 11209 break; 11210 case TUNNEL_CREATE: 11211 case TUNNEL_DESTROY: 11212 case TUNNEL_LIST: 11213 out->command = ctx->curr; 11214 break; 11215 case TUNNEL_CREATE_TYPE: 11216 case TUNNEL_DESTROY_ID: 11217 ctx->object = &out->args.vc.tunnel_ops; 11218 break; 11219 } 11220 } 11221 11222 return len; 11223 } 11224 11225 /** 11226 * Parse signed/unsigned integers 8 to 64-bit long. 11227 * 11228 * Last argument (ctx->args) is retrieved to determine integer type and 11229 * storage location. 11230 */ 11231 static int 11232 parse_int(struct context *ctx, const struct token *token, 11233 const char *str, unsigned int len, 11234 void *buf, unsigned int size) 11235 { 11236 const struct arg *arg = pop_args(ctx); 11237 uintmax_t u; 11238 char *end; 11239 11240 (void)token; 11241 /* Argument is expected. */ 11242 if (!arg) 11243 return -1; 11244 errno = 0; 11245 u = arg->sign ? 11246 (uintmax_t)strtoimax(str, &end, 0) : 11247 strtoumax(str, &end, 0); 11248 if (errno || (size_t)(end - str) != len) 11249 goto error; 11250 if (arg->bounded && 11251 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min || 11252 (intmax_t)u > (intmax_t)arg->max)) || 11253 (!arg->sign && (u < arg->min || u > arg->max)))) 11254 goto error; 11255 if (!ctx->object) 11256 return len; 11257 if (arg->mask) { 11258 if (!arg_entry_bf_fill(ctx->object, u, arg) || 11259 !arg_entry_bf_fill(ctx->objmask, -1, arg)) 11260 goto error; 11261 return len; 11262 } 11263 buf = (uint8_t *)ctx->object + arg->offset; 11264 size = arg->size; 11265 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t)) 11266 return -1; 11267 objmask: 11268 switch (size) { 11269 case sizeof(uint8_t): 11270 *(uint8_t *)buf = u; 11271 break; 11272 case sizeof(uint16_t): 11273 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u; 11274 break; 11275 case sizeof(uint8_t [3]): 11276 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 11277 if (!arg->hton) { 11278 ((uint8_t *)buf)[0] = u; 11279 ((uint8_t *)buf)[1] = u >> 8; 11280 ((uint8_t *)buf)[2] = u >> 16; 11281 break; 11282 } 11283 #endif 11284 ((uint8_t *)buf)[0] = u >> 16; 11285 ((uint8_t *)buf)[1] = u >> 8; 11286 ((uint8_t *)buf)[2] = u; 11287 break; 11288 case sizeof(uint32_t): 11289 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u; 11290 break; 11291 case sizeof(uint64_t): 11292 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u; 11293 break; 11294 default: 11295 goto error; 11296 } 11297 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) { 11298 u = -1; 11299 buf = (uint8_t *)ctx->objmask + arg->offset; 11300 goto objmask; 11301 } 11302 return len; 11303 error: 11304 push_args(ctx, arg); 11305 return -1; 11306 } 11307 11308 /** 11309 * Parse a string. 11310 * 11311 * Three arguments (ctx->args) are retrieved from the stack to store data, 11312 * its actual length and address (in that order). 11313 */ 11314 static int 11315 parse_string(struct context *ctx, const struct token *token, 11316 const char *str, unsigned int len, 11317 void *buf, unsigned int size) 11318 { 11319 const struct arg *arg_data = pop_args(ctx); 11320 const struct arg *arg_len = pop_args(ctx); 11321 const struct arg *arg_addr = pop_args(ctx); 11322 char tmp[16]; /* Ought to be enough. */ 11323 int ret; 11324 11325 /* Arguments are expected. */ 11326 if (!arg_data) 11327 return -1; 11328 if (!arg_len) { 11329 push_args(ctx, arg_data); 11330 return -1; 11331 } 11332 if (!arg_addr) { 11333 push_args(ctx, arg_len); 11334 push_args(ctx, arg_data); 11335 return -1; 11336 } 11337 size = arg_data->size; 11338 /* Bit-mask fill is not supported. */ 11339 if (arg_data->mask || size < len) 11340 goto error; 11341 if (!ctx->object) 11342 return len; 11343 /* Let parse_int() fill length information first. */ 11344 ret = snprintf(tmp, sizeof(tmp), "%u", len); 11345 if (ret < 0) 11346 goto error; 11347 push_args(ctx, arg_len); 11348 ret = parse_int(ctx, token, tmp, ret, NULL, 0); 11349 if (ret < 0) { 11350 pop_args(ctx); 11351 goto error; 11352 } 11353 buf = (uint8_t *)ctx->object + arg_data->offset; 11354 /* Output buffer is not necessarily NUL-terminated. */ 11355 memcpy(buf, str, len); 11356 memset((uint8_t *)buf + len, 0x00, size - len); 11357 if (ctx->objmask) 11358 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len); 11359 /* Save address if requested. */ 11360 if (arg_addr->size) { 11361 memcpy((uint8_t *)ctx->object + arg_addr->offset, 11362 (void *[]){ 11363 (uint8_t *)ctx->object + arg_data->offset 11364 }, 11365 arg_addr->size); 11366 if (ctx->objmask) 11367 memcpy((uint8_t *)ctx->objmask + arg_addr->offset, 11368 (void *[]){ 11369 (uint8_t *)ctx->objmask + arg_data->offset 11370 }, 11371 arg_addr->size); 11372 } 11373 return len; 11374 error: 11375 push_args(ctx, arg_addr); 11376 push_args(ctx, arg_len); 11377 push_args(ctx, arg_data); 11378 return -1; 11379 } 11380 11381 static int 11382 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size) 11383 { 11384 const uint8_t *head = dst; 11385 uint32_t left; 11386 11387 if (*size == 0) 11388 return -1; 11389 11390 left = *size; 11391 11392 /* Convert chars to bytes */ 11393 while (left) { 11394 char tmp[3], *end = tmp; 11395 uint32_t read_lim = left & 1 ? 1 : 2; 11396 11397 snprintf(tmp, read_lim + 1, "%s", src); 11398 *dst = strtoul(tmp, &end, 16); 11399 if (*end) { 11400 *dst = 0; 11401 *size = (uint32_t)(dst - head); 11402 return -1; 11403 } 11404 left -= read_lim; 11405 src += read_lim; 11406 dst++; 11407 } 11408 *dst = 0; 11409 *size = (uint32_t)(dst - head); 11410 return 0; 11411 } 11412 11413 static int 11414 parse_hex(struct context *ctx, const struct token *token, 11415 const char *str, unsigned int len, 11416 void *buf, unsigned int size) 11417 { 11418 const struct arg *arg_data = pop_args(ctx); 11419 const struct arg *arg_len = pop_args(ctx); 11420 const struct arg *arg_addr = pop_args(ctx); 11421 char tmp[16]; /* Ought to be enough. */ 11422 int ret; 11423 unsigned int hexlen = len; 11424 unsigned int length = 256; 11425 uint8_t hex_tmp[length]; 11426 11427 /* Arguments are expected. */ 11428 if (!arg_data) 11429 return -1; 11430 if (!arg_len) { 11431 push_args(ctx, arg_data); 11432 return -1; 11433 } 11434 if (!arg_addr) { 11435 push_args(ctx, arg_len); 11436 push_args(ctx, arg_data); 11437 return -1; 11438 } 11439 size = arg_data->size; 11440 /* Bit-mask fill is not supported. */ 11441 if (arg_data->mask) 11442 goto error; 11443 if (!ctx->object) 11444 return len; 11445 11446 /* translate bytes string to array. */ 11447 if (str[0] == '0' && ((str[1] == 'x') || 11448 (str[1] == 'X'))) { 11449 str += 2; 11450 hexlen -= 2; 11451 } 11452 if (hexlen > length) 11453 goto error; 11454 ret = parse_hex_string(str, hex_tmp, &hexlen); 11455 if (ret < 0) 11456 goto error; 11457 /* Check the converted binary fits into data buffer. */ 11458 if (hexlen > size) 11459 goto error; 11460 /* Let parse_int() fill length information first. */ 11461 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen); 11462 if (ret < 0) 11463 goto error; 11464 /* Save length if requested. */ 11465 if (arg_len->size) { 11466 push_args(ctx, arg_len); 11467 ret = parse_int(ctx, token, tmp, ret, NULL, 0); 11468 if (ret < 0) { 11469 pop_args(ctx); 11470 goto error; 11471 } 11472 } 11473 buf = (uint8_t *)ctx->object + arg_data->offset; 11474 /* Output buffer is not necessarily NUL-terminated. */ 11475 memcpy(buf, hex_tmp, hexlen); 11476 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen); 11477 if (ctx->objmask) 11478 memset((uint8_t *)ctx->objmask + arg_data->offset, 11479 0xff, hexlen); 11480 /* Save address if requested. */ 11481 if (arg_addr->size) { 11482 memcpy((uint8_t *)ctx->object + arg_addr->offset, 11483 (void *[]){ 11484 (uint8_t *)ctx->object + arg_data->offset 11485 }, 11486 arg_addr->size); 11487 if (ctx->objmask) 11488 memcpy((uint8_t *)ctx->objmask + arg_addr->offset, 11489 (void *[]){ 11490 (uint8_t *)ctx->objmask + arg_data->offset 11491 }, 11492 arg_addr->size); 11493 } 11494 return len; 11495 error: 11496 push_args(ctx, arg_addr); 11497 push_args(ctx, arg_len); 11498 push_args(ctx, arg_data); 11499 return -1; 11500 11501 } 11502 11503 /** 11504 * Parse a zero-ended string. 11505 */ 11506 static int 11507 parse_string0(struct context *ctx, const struct token *token __rte_unused, 11508 const char *str, unsigned int len, 11509 void *buf, unsigned int size) 11510 { 11511 const struct arg *arg_data = pop_args(ctx); 11512 11513 /* Arguments are expected. */ 11514 if (!arg_data) 11515 return -1; 11516 size = arg_data->size; 11517 /* Bit-mask fill is not supported. */ 11518 if (arg_data->mask || size < len + 1) 11519 goto error; 11520 if (!ctx->object) 11521 return len; 11522 buf = (uint8_t *)ctx->object + arg_data->offset; 11523 strncpy(buf, str, len); 11524 if (ctx->objmask) 11525 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len); 11526 return len; 11527 error: 11528 push_args(ctx, arg_data); 11529 return -1; 11530 } 11531 11532 /** 11533 * Parse a MAC address. 11534 * 11535 * Last argument (ctx->args) is retrieved to determine storage size and 11536 * location. 11537 */ 11538 static int 11539 parse_mac_addr(struct context *ctx, const struct token *token, 11540 const char *str, unsigned int len, 11541 void *buf, unsigned int size) 11542 { 11543 const struct arg *arg = pop_args(ctx); 11544 struct rte_ether_addr tmp; 11545 int ret; 11546 11547 (void)token; 11548 /* Argument is expected. */ 11549 if (!arg) 11550 return -1; 11551 size = arg->size; 11552 /* Bit-mask fill is not supported. */ 11553 if (arg->mask || size != sizeof(tmp)) 11554 goto error; 11555 /* Only network endian is supported. */ 11556 if (!arg->hton) 11557 goto error; 11558 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size); 11559 if (ret < 0 || (unsigned int)ret != len) 11560 goto error; 11561 if (!ctx->object) 11562 return len; 11563 buf = (uint8_t *)ctx->object + arg->offset; 11564 memcpy(buf, &tmp, size); 11565 if (ctx->objmask) 11566 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 11567 return len; 11568 error: 11569 push_args(ctx, arg); 11570 return -1; 11571 } 11572 11573 /** 11574 * Parse an IPv4 address. 11575 * 11576 * Last argument (ctx->args) is retrieved to determine storage size and 11577 * location. 11578 */ 11579 static int 11580 parse_ipv4_addr(struct context *ctx, const struct token *token, 11581 const char *str, unsigned int len, 11582 void *buf, unsigned int size) 11583 { 11584 const struct arg *arg = pop_args(ctx); 11585 char str2[len + 1]; 11586 struct in_addr tmp; 11587 int ret; 11588 11589 /* Argument is expected. */ 11590 if (!arg) 11591 return -1; 11592 size = arg->size; 11593 /* Bit-mask fill is not supported. */ 11594 if (arg->mask || size != sizeof(tmp)) 11595 goto error; 11596 /* Only network endian is supported. */ 11597 if (!arg->hton) 11598 goto error; 11599 memcpy(str2, str, len); 11600 str2[len] = '\0'; 11601 ret = inet_pton(AF_INET, str2, &tmp); 11602 if (ret != 1) { 11603 /* Attempt integer parsing. */ 11604 push_args(ctx, arg); 11605 return parse_int(ctx, token, str, len, buf, size); 11606 } 11607 if (!ctx->object) 11608 return len; 11609 buf = (uint8_t *)ctx->object + arg->offset; 11610 memcpy(buf, &tmp, size); 11611 if (ctx->objmask) 11612 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 11613 return len; 11614 error: 11615 push_args(ctx, arg); 11616 return -1; 11617 } 11618 11619 /** 11620 * Parse an IPv6 address. 11621 * 11622 * Last argument (ctx->args) is retrieved to determine storage size and 11623 * location. 11624 */ 11625 static int 11626 parse_ipv6_addr(struct context *ctx, const struct token *token, 11627 const char *str, unsigned int len, 11628 void *buf, unsigned int size) 11629 { 11630 const struct arg *arg = pop_args(ctx); 11631 char str2[len + 1]; 11632 struct in6_addr tmp; 11633 int ret; 11634 11635 (void)token; 11636 /* Argument is expected. */ 11637 if (!arg) 11638 return -1; 11639 size = arg->size; 11640 /* Bit-mask fill is not supported. */ 11641 if (arg->mask || size != sizeof(tmp)) 11642 goto error; 11643 /* Only network endian is supported. */ 11644 if (!arg->hton) 11645 goto error; 11646 memcpy(str2, str, len); 11647 str2[len] = '\0'; 11648 ret = inet_pton(AF_INET6, str2, &tmp); 11649 if (ret != 1) 11650 goto error; 11651 if (!ctx->object) 11652 return len; 11653 buf = (uint8_t *)ctx->object + arg->offset; 11654 memcpy(buf, &tmp, size); 11655 if (ctx->objmask) 11656 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 11657 return len; 11658 error: 11659 push_args(ctx, arg); 11660 return -1; 11661 } 11662 11663 /** Boolean values (even indices stand for false). */ 11664 static const char *const boolean_name[] = { 11665 "0", "1", 11666 "false", "true", 11667 "no", "yes", 11668 "N", "Y", 11669 "off", "on", 11670 NULL, 11671 }; 11672 11673 /** 11674 * Parse a boolean value. 11675 * 11676 * Last argument (ctx->args) is retrieved to determine storage size and 11677 * location. 11678 */ 11679 static int 11680 parse_boolean(struct context *ctx, const struct token *token, 11681 const char *str, unsigned int len, 11682 void *buf, unsigned int size) 11683 { 11684 const struct arg *arg = pop_args(ctx); 11685 unsigned int i; 11686 int ret; 11687 11688 /* Argument is expected. */ 11689 if (!arg) 11690 return -1; 11691 for (i = 0; boolean_name[i]; ++i) 11692 if (!strcmp_partial(boolean_name[i], str, len)) 11693 break; 11694 /* Process token as integer. */ 11695 if (boolean_name[i]) 11696 str = i & 1 ? "1" : "0"; 11697 push_args(ctx, arg); 11698 ret = parse_int(ctx, token, str, strlen(str), buf, size); 11699 return ret > 0 ? (int)len : ret; 11700 } 11701 11702 /** Parse port and update context. */ 11703 static int 11704 parse_port(struct context *ctx, const struct token *token, 11705 const char *str, unsigned int len, 11706 void *buf, unsigned int size) 11707 { 11708 struct buffer *out = &(struct buffer){ .port = 0 }; 11709 int ret; 11710 11711 if (buf) 11712 out = buf; 11713 else { 11714 ctx->objdata = 0; 11715 ctx->object = out; 11716 ctx->objmask = NULL; 11717 size = sizeof(*out); 11718 } 11719 ret = parse_int(ctx, token, str, len, out, size); 11720 if (ret >= 0) 11721 ctx->port = out->port; 11722 if (!buf) 11723 ctx->object = NULL; 11724 return ret; 11725 } 11726 11727 /** Parse tokens for shared indirect actions. */ 11728 static int 11729 parse_ia_port(struct context *ctx, const struct token *token, 11730 const char *str, unsigned int len, 11731 void *buf, unsigned int size) 11732 { 11733 struct rte_flow_action *action = ctx->object; 11734 uint32_t id; 11735 int ret; 11736 11737 (void)buf; 11738 (void)size; 11739 ctx->objdata = 0; 11740 ctx->object = &id; 11741 ctx->objmask = NULL; 11742 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id)); 11743 ctx->object = action; 11744 if (ret != (int)len) 11745 return ret; 11746 /* set indirect action */ 11747 if (action) 11748 action->conf = (void *)(uintptr_t)id; 11749 return ret; 11750 } 11751 11752 static int 11753 parse_ia_id2ptr(struct context *ctx, const struct token *token, 11754 const char *str, unsigned int len, 11755 void *buf, unsigned int size) 11756 { 11757 struct rte_flow_action *action = ctx->object; 11758 uint32_t id; 11759 int ret; 11760 11761 (void)buf; 11762 (void)size; 11763 ctx->objdata = 0; 11764 ctx->object = &id; 11765 ctx->objmask = NULL; 11766 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id)); 11767 ctx->object = action; 11768 if (ret != (int)len) 11769 return ret; 11770 /* set indirect action */ 11771 if (action) { 11772 portid_t port_id = ctx->port; 11773 if (ctx->prev == INDIRECT_ACTION_PORT) 11774 port_id = (portid_t)(uintptr_t)action->conf; 11775 action->conf = port_action_handle_get_by_id(port_id, id); 11776 ret = (action->conf) ? ret : -1; 11777 } 11778 return ret; 11779 } 11780 11781 static int 11782 parse_indlst_id2ptr(struct context *ctx, const struct token *token, 11783 const char *str, unsigned int len, 11784 __rte_unused void *buf, __rte_unused unsigned int size) 11785 { 11786 struct rte_flow_action *action = ctx->object; 11787 struct rte_flow_action_indirect_list *action_conf; 11788 const struct indlst_conf *indlst_conf; 11789 uint32_t id; 11790 int ret; 11791 11792 if (!action) 11793 return -1; 11794 ctx->objdata = 0; 11795 ctx->object = &id; 11796 ctx->objmask = NULL; 11797 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id)); 11798 if (ret != (int)len) 11799 return ret; 11800 ctx->object = action; 11801 action_conf = (void *)(uintptr_t)action->conf; 11802 action_conf->conf = NULL; 11803 switch (ctx->curr) { 11804 case INDIRECT_LIST_ACTION_ID2PTR_HANDLE: 11805 action_conf->handle = (typeof(action_conf->handle)) 11806 port_action_handle_get_by_id(ctx->port, id); 11807 if (!action_conf->handle) { 11808 printf("no indirect list handle for id %u\n", id); 11809 return -1; 11810 } 11811 break; 11812 case INDIRECT_LIST_ACTION_ID2PTR_CONF: 11813 indlst_conf = indirect_action_list_conf_get(id); 11814 if (!indlst_conf) 11815 return -1; 11816 action_conf->conf = (const void **)indlst_conf->conf; 11817 break; 11818 default: 11819 break; 11820 } 11821 return ret; 11822 } 11823 11824 static int 11825 parse_meter_profile_id2ptr(struct context *ctx, const struct token *token, 11826 const char *str, unsigned int len, 11827 void *buf, unsigned int size) 11828 { 11829 struct rte_flow_action *action = ctx->object; 11830 struct rte_flow_action_meter_mark *meter; 11831 struct rte_flow_meter_profile *profile = NULL; 11832 uint32_t id = 0; 11833 int ret; 11834 11835 (void)buf; 11836 (void)size; 11837 ctx->objdata = 0; 11838 ctx->object = &id; 11839 ctx->objmask = NULL; 11840 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id)); 11841 ctx->object = action; 11842 if (ret != (int)len) 11843 return ret; 11844 /* set meter profile */ 11845 if (action) { 11846 meter = (struct rte_flow_action_meter_mark *) 11847 (uintptr_t)(action->conf); 11848 profile = port_meter_profile_get_by_id(ctx->port, id); 11849 meter->profile = profile; 11850 ret = (profile) ? ret : -1; 11851 } 11852 return ret; 11853 } 11854 11855 static int 11856 parse_meter_policy_id2ptr(struct context *ctx, const struct token *token, 11857 const char *str, unsigned int len, 11858 void *buf, unsigned int size) 11859 { 11860 struct rte_flow_action *action = ctx->object; 11861 struct rte_flow_action_meter_mark *meter; 11862 struct rte_flow_meter_policy *policy = NULL; 11863 uint32_t id = 0; 11864 int ret; 11865 11866 (void)buf; 11867 (void)size; 11868 ctx->objdata = 0; 11869 ctx->object = &id; 11870 ctx->objmask = NULL; 11871 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id)); 11872 ctx->object = action; 11873 if (ret != (int)len) 11874 return ret; 11875 /* set meter policy */ 11876 if (action) { 11877 meter = (struct rte_flow_action_meter_mark *) 11878 (uintptr_t)(action->conf); 11879 policy = port_meter_policy_get_by_id(ctx->port, id); 11880 meter->policy = policy; 11881 ret = (policy) ? ret : -1; 11882 } 11883 return ret; 11884 } 11885 11886 /** Parse set command, initialize output buffer for subsequent tokens. */ 11887 static int 11888 parse_set_raw_encap_decap(struct context *ctx, const struct token *token, 11889 const char *str, unsigned int len, 11890 void *buf, unsigned int size) 11891 { 11892 struct buffer *out = buf; 11893 11894 /* Token name must match. */ 11895 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 11896 return -1; 11897 /* Nothing else to do if there is no buffer. */ 11898 if (!out) 11899 return len; 11900 /* Make sure buffer is large enough. */ 11901 if (size < sizeof(*out)) 11902 return -1; 11903 ctx->objdata = 0; 11904 ctx->objmask = NULL; 11905 ctx->object = out; 11906 if (!out->command) 11907 return -1; 11908 out->command = ctx->curr; 11909 /* For encap/decap we need is pattern */ 11910 out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 11911 sizeof(double)); 11912 return len; 11913 } 11914 11915 /** Parse set command, initialize output buffer for subsequent tokens. */ 11916 static int 11917 parse_set_sample_action(struct context *ctx, const struct token *token, 11918 const char *str, unsigned int len, 11919 void *buf, unsigned int size) 11920 { 11921 struct buffer *out = buf; 11922 11923 /* Token name must match. */ 11924 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 11925 return -1; 11926 /* Nothing else to do if there is no buffer. */ 11927 if (!out) 11928 return len; 11929 /* Make sure buffer is large enough. */ 11930 if (size < sizeof(*out)) 11931 return -1; 11932 ctx->objdata = 0; 11933 ctx->objmask = NULL; 11934 ctx->object = out; 11935 if (!out->command) 11936 return -1; 11937 out->command = ctx->curr; 11938 /* For sampler we need is actions */ 11939 out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 11940 sizeof(double)); 11941 return len; 11942 } 11943 11944 /** Parse set command, initialize output buffer for subsequent tokens. */ 11945 static int 11946 parse_set_ipv6_ext_action(struct context *ctx, const struct token *token, 11947 const char *str, unsigned int len, 11948 void *buf, unsigned int size) 11949 { 11950 struct buffer *out = buf; 11951 11952 /* Token name must match. */ 11953 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 11954 return -1; 11955 /* Nothing else to do if there is no buffer. */ 11956 if (!out) 11957 return len; 11958 /* Make sure buffer is large enough. */ 11959 if (size < sizeof(*out)) 11960 return -1; 11961 ctx->objdata = 0; 11962 ctx->objmask = NULL; 11963 ctx->object = out; 11964 if (!out->command) 11965 return -1; 11966 out->command = ctx->curr; 11967 /* For ipv6_ext_push/remove we need is pattern */ 11968 out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 11969 sizeof(double)); 11970 return len; 11971 } 11972 11973 /** 11974 * Parse set raw_encap/raw_decap command, 11975 * initialize output buffer for subsequent tokens. 11976 */ 11977 static int 11978 parse_set_init(struct context *ctx, const struct token *token, 11979 const char *str, unsigned int len, 11980 void *buf, unsigned int size) 11981 { 11982 struct buffer *out = buf; 11983 11984 /* Token name must match. */ 11985 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 11986 return -1; 11987 /* Nothing else to do if there is no buffer. */ 11988 if (!out) 11989 return len; 11990 /* Make sure buffer is large enough. */ 11991 if (size < sizeof(*out)) 11992 return -1; 11993 /* Initialize buffer. */ 11994 memset(out, 0x00, sizeof(*out)); 11995 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out)); 11996 ctx->objdata = 0; 11997 ctx->object = out; 11998 ctx->objmask = NULL; 11999 if (!out->command) { 12000 if (ctx->curr != SET) 12001 return -1; 12002 if (sizeof(*out) > size) 12003 return -1; 12004 out->command = ctx->curr; 12005 out->args.vc.data = (uint8_t *)out + size; 12006 ctx->object = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 12007 sizeof(double)); 12008 } 12009 return len; 12010 } 12011 12012 /* 12013 * Replace testpmd handles in a flex flow item with real values. 12014 */ 12015 static int 12016 parse_flex_handle(struct context *ctx, const struct token *token, 12017 const char *str, unsigned int len, 12018 void *buf, unsigned int size) 12019 { 12020 struct rte_flow_item_flex *spec, *mask; 12021 const struct rte_flow_item_flex *src_spec, *src_mask; 12022 const struct arg *arg = pop_args(ctx); 12023 uint32_t offset; 12024 uint16_t handle; 12025 int ret; 12026 12027 if (!arg) { 12028 printf("Bad environment\n"); 12029 return -1; 12030 } 12031 offset = arg->offset; 12032 push_args(ctx, arg); 12033 ret = parse_int(ctx, token, str, len, buf, size); 12034 if (ret <= 0 || !ctx->object) 12035 return ret; 12036 if (ctx->port >= RTE_MAX_ETHPORTS) { 12037 printf("Bad port\n"); 12038 return -1; 12039 } 12040 if (offset == offsetof(struct rte_flow_item_flex, handle)) { 12041 const struct flex_item *fp; 12042 spec = ctx->object; 12043 handle = (uint16_t)(uintptr_t)spec->handle; 12044 if (handle >= FLEX_MAX_PARSERS_NUM) { 12045 printf("Bad flex item handle\n"); 12046 return -1; 12047 } 12048 fp = flex_items[ctx->port][handle]; 12049 if (!fp) { 12050 printf("Bad flex item handle\n"); 12051 return -1; 12052 } 12053 spec->handle = fp->flex_handle; 12054 mask = spec + 2; /* spec, last, mask */ 12055 mask->handle = fp->flex_handle; 12056 } else if (offset == offsetof(struct rte_flow_item_flex, pattern)) { 12057 handle = (uint16_t)(uintptr_t) 12058 ((struct rte_flow_item_flex *)ctx->object)->pattern; 12059 if (handle >= FLEX_MAX_PATTERNS_NUM) { 12060 printf("Bad pattern handle\n"); 12061 return -1; 12062 } 12063 src_spec = &flex_patterns[handle].spec; 12064 src_mask = &flex_patterns[handle].mask; 12065 spec = ctx->object; 12066 mask = spec + 2; /* spec, last, mask */ 12067 /* fill flow rule spec and mask parameters */ 12068 spec->length = src_spec->length; 12069 spec->pattern = src_spec->pattern; 12070 mask->length = src_mask->length; 12071 mask->pattern = src_mask->pattern; 12072 } else { 12073 printf("Bad arguments - unknown flex item offset\n"); 12074 return -1; 12075 } 12076 return ret; 12077 } 12078 12079 /** Parse Meter color name */ 12080 static int 12081 parse_meter_color(struct context *ctx, const struct token *token, 12082 const char *str, unsigned int len, void *buf, 12083 unsigned int size) 12084 { 12085 struct rte_flow_item_meter_color *meter_color; 12086 unsigned int i; 12087 12088 (void)token; 12089 (void)buf; 12090 (void)size; 12091 for (i = 0; meter_colors[i]; ++i) 12092 if (!strcmp_partial(meter_colors[i], str, len)) 12093 break; 12094 if (!meter_colors[i]) 12095 return -1; 12096 if (!ctx->object) 12097 return len; 12098 meter_color = ctx->object; 12099 meter_color->color = (enum rte_color)i; 12100 return len; 12101 } 12102 12103 /** Parse Insertion Table Type name */ 12104 static int 12105 parse_insertion_table_type(struct context *ctx, const struct token *token, 12106 const char *str, unsigned int len, void *buf, 12107 unsigned int size) 12108 { 12109 const struct arg *arg = pop_args(ctx); 12110 unsigned int i; 12111 char tmp[2]; 12112 int ret; 12113 12114 (void)size; 12115 /* Argument is expected. */ 12116 if (!arg) 12117 return -1; 12118 for (i = 0; table_insertion_types[i]; ++i) 12119 if (!strcmp_partial(table_insertion_types[i], str, len)) 12120 break; 12121 if (!table_insertion_types[i]) 12122 return -1; 12123 push_args(ctx, arg); 12124 snprintf(tmp, sizeof(tmp), "%u", i); 12125 ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i)); 12126 return ret > 0 ? (int)len : ret; 12127 } 12128 12129 /** Parse Hash Calculation Table Type name */ 12130 static int 12131 parse_hash_table_type(struct context *ctx, const struct token *token, 12132 const char *str, unsigned int len, void *buf, 12133 unsigned int size) 12134 { 12135 const struct arg *arg = pop_args(ctx); 12136 unsigned int i; 12137 char tmp[2]; 12138 int ret; 12139 12140 (void)size; 12141 /* Argument is expected. */ 12142 if (!arg) 12143 return -1; 12144 for (i = 0; table_hash_funcs[i]; ++i) 12145 if (!strcmp_partial(table_hash_funcs[i], str, len)) 12146 break; 12147 if (!table_hash_funcs[i]) 12148 return -1; 12149 push_args(ctx, arg); 12150 snprintf(tmp, sizeof(tmp), "%u", i); 12151 ret = parse_int(ctx, token, tmp, strlen(tmp), buf, sizeof(i)); 12152 return ret > 0 ? (int)len : ret; 12153 } 12154 12155 static int 12156 parse_name_to_index(struct context *ctx, const struct token *token, 12157 const char *str, unsigned int len, void *buf, 12158 unsigned int size, 12159 const char *const names[], size_t names_size, uint32_t *dst) 12160 { 12161 int ret; 12162 uint32_t i; 12163 12164 RTE_SET_USED(token); 12165 RTE_SET_USED(buf); 12166 RTE_SET_USED(size); 12167 if (!ctx->object) 12168 return len; 12169 for (i = 0; i < names_size; i++) { 12170 if (!names[i]) 12171 continue; 12172 ret = strcmp_partial(names[i], str, 12173 RTE_MIN(len, strlen(names[i]))); 12174 if (!ret) { 12175 *dst = i; 12176 return len; 12177 } 12178 } 12179 return -1; 12180 } 12181 12182 static const char *const quota_mode_names[] = { 12183 NULL, 12184 [RTE_FLOW_QUOTA_MODE_PACKET] = "packet", 12185 [RTE_FLOW_QUOTA_MODE_L2] = "l2", 12186 [RTE_FLOW_QUOTA_MODE_L3] = "l3" 12187 }; 12188 12189 static const char *const quota_state_names[] = { 12190 [RTE_FLOW_QUOTA_STATE_PASS] = "pass", 12191 [RTE_FLOW_QUOTA_STATE_BLOCK] = "block" 12192 }; 12193 12194 static const char *const quota_update_names[] = { 12195 [RTE_FLOW_UPDATE_QUOTA_SET] = "set", 12196 [RTE_FLOW_UPDATE_QUOTA_ADD] = "add" 12197 }; 12198 12199 static const char *const query_update_mode_names[] = { 12200 [RTE_FLOW_QU_QUERY_FIRST] = "query_first", 12201 [RTE_FLOW_QU_UPDATE_FIRST] = "update_first" 12202 }; 12203 12204 static int 12205 parse_quota_state_name(struct context *ctx, const struct token *token, 12206 const char *str, unsigned int len, void *buf, 12207 unsigned int size) 12208 { 12209 struct rte_flow_item_quota *quota = ctx->object; 12210 12211 return parse_name_to_index(ctx, token, str, len, buf, size, 12212 quota_state_names, 12213 RTE_DIM(quota_state_names), 12214 (uint32_t *)"a->state); 12215 } 12216 12217 static int 12218 parse_quota_mode_name(struct context *ctx, const struct token *token, 12219 const char *str, unsigned int len, void *buf, 12220 unsigned int size) 12221 { 12222 struct rte_flow_action_quota *quota = ctx->object; 12223 12224 return parse_name_to_index(ctx, token, str, len, buf, size, 12225 quota_mode_names, 12226 RTE_DIM(quota_mode_names), 12227 (uint32_t *)"a->mode); 12228 } 12229 12230 static int 12231 parse_quota_update_name(struct context *ctx, const struct token *token, 12232 const char *str, unsigned int len, void *buf, 12233 unsigned int size) 12234 { 12235 struct rte_flow_update_quota *update = ctx->object; 12236 12237 return parse_name_to_index(ctx, token, str, len, buf, size, 12238 quota_update_names, 12239 RTE_DIM(quota_update_names), 12240 (uint32_t *)&update->op); 12241 } 12242 12243 static int 12244 parse_qu_mode_name(struct context *ctx, const struct token *token, 12245 const char *str, unsigned int len, void *buf, 12246 unsigned int size) 12247 { 12248 struct buffer *out = ctx->object; 12249 12250 return parse_name_to_index(ctx, token, str, len, buf, size, 12251 query_update_mode_names, 12252 RTE_DIM(query_update_mode_names), 12253 (uint32_t *)&out->args.ia.qu_mode); 12254 } 12255 12256 /** No completion. */ 12257 static int 12258 comp_none(struct context *ctx, const struct token *token, 12259 unsigned int ent, char *buf, unsigned int size) 12260 { 12261 (void)ctx; 12262 (void)token; 12263 (void)ent; 12264 (void)buf; 12265 (void)size; 12266 return 0; 12267 } 12268 12269 /** Complete boolean values. */ 12270 static int 12271 comp_boolean(struct context *ctx, const struct token *token, 12272 unsigned int ent, char *buf, unsigned int size) 12273 { 12274 unsigned int i; 12275 12276 (void)ctx; 12277 (void)token; 12278 for (i = 0; boolean_name[i]; ++i) 12279 if (buf && i == ent) 12280 return strlcpy(buf, boolean_name[i], size); 12281 if (buf) 12282 return -1; 12283 return i; 12284 } 12285 12286 /** Complete action names. */ 12287 static int 12288 comp_action(struct context *ctx, const struct token *token, 12289 unsigned int ent, char *buf, unsigned int size) 12290 { 12291 unsigned int i; 12292 12293 (void)ctx; 12294 (void)token; 12295 for (i = 0; next_action[i]; ++i) 12296 if (buf && i == ent) 12297 return strlcpy(buf, token_list[next_action[i]].name, 12298 size); 12299 if (buf) 12300 return -1; 12301 return i; 12302 } 12303 12304 /** Complete available ports. */ 12305 static int 12306 comp_port(struct context *ctx, const struct token *token, 12307 unsigned int ent, char *buf, unsigned int size) 12308 { 12309 unsigned int i = 0; 12310 portid_t p; 12311 12312 (void)ctx; 12313 (void)token; 12314 RTE_ETH_FOREACH_DEV(p) { 12315 if (buf && i == ent) 12316 return snprintf(buf, size, "%u", p); 12317 ++i; 12318 } 12319 if (buf) 12320 return -1; 12321 return i; 12322 } 12323 12324 /** Complete available rule IDs. */ 12325 static int 12326 comp_rule_id(struct context *ctx, const struct token *token, 12327 unsigned int ent, char *buf, unsigned int size) 12328 { 12329 unsigned int i = 0; 12330 struct rte_port *port; 12331 struct port_flow *pf; 12332 12333 (void)token; 12334 if (port_id_is_invalid(ctx->port, DISABLED_WARN) || 12335 ctx->port == (portid_t)RTE_PORT_ALL) 12336 return -1; 12337 port = &ports[ctx->port]; 12338 for (pf = port->flow_list; pf != NULL; pf = pf->next) { 12339 if (buf && i == ent) 12340 return snprintf(buf, size, "%"PRIu64, pf->id); 12341 ++i; 12342 } 12343 if (buf) 12344 return -1; 12345 return i; 12346 } 12347 12348 /** Complete operation for compare match item. */ 12349 static int 12350 comp_set_compare_op(struct context *ctx, const struct token *token, 12351 unsigned int ent, char *buf, unsigned int size) 12352 { 12353 RTE_SET_USED(ctx); 12354 RTE_SET_USED(token); 12355 if (!buf) 12356 return RTE_DIM(compare_ops); 12357 if (ent < RTE_DIM(compare_ops) - 1) 12358 return strlcpy(buf, compare_ops[ent], size); 12359 return -1; 12360 } 12361 12362 /** Complete field id for compare match item. */ 12363 static int 12364 comp_set_compare_field_id(struct context *ctx, const struct token *token, 12365 unsigned int ent, char *buf, unsigned int size) 12366 { 12367 const char *name; 12368 12369 RTE_SET_USED(token); 12370 if (!buf) 12371 return RTE_DIM(flow_field_ids); 12372 if (ent >= RTE_DIM(flow_field_ids) - 1) 12373 return -1; 12374 name = flow_field_ids[ent]; 12375 if (ctx->curr == ITEM_COMPARE_FIELD_B_TYPE || 12376 (strcmp(name, "pointer") && strcmp(name, "value"))) 12377 return strlcpy(buf, name, size); 12378 return -1; 12379 } 12380 12381 /** Complete type field for RSS action. */ 12382 static int 12383 comp_vc_action_rss_type(struct context *ctx, const struct token *token, 12384 unsigned int ent, char *buf, unsigned int size) 12385 { 12386 unsigned int i; 12387 12388 (void)ctx; 12389 (void)token; 12390 for (i = 0; rss_type_table[i].str; ++i) 12391 ; 12392 if (!buf) 12393 return i + 1; 12394 if (ent < i) 12395 return strlcpy(buf, rss_type_table[ent].str, size); 12396 if (ent == i) 12397 return snprintf(buf, size, "end"); 12398 return -1; 12399 } 12400 12401 /** Complete queue field for RSS action. */ 12402 static int 12403 comp_vc_action_rss_queue(struct context *ctx, const struct token *token, 12404 unsigned int ent, char *buf, unsigned int size) 12405 { 12406 (void)ctx; 12407 (void)token; 12408 if (!buf) 12409 return nb_rxq + 1; 12410 if (ent < nb_rxq) 12411 return snprintf(buf, size, "%u", ent); 12412 if (ent == nb_rxq) 12413 return snprintf(buf, size, "end"); 12414 return -1; 12415 } 12416 12417 /** Complete index number for set raw_encap/raw_decap commands. */ 12418 static int 12419 comp_set_raw_index(struct context *ctx, const struct token *token, 12420 unsigned int ent, char *buf, unsigned int size) 12421 { 12422 uint16_t idx = 0; 12423 uint16_t nb = 0; 12424 12425 RTE_SET_USED(ctx); 12426 RTE_SET_USED(token); 12427 for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) { 12428 if (buf && idx == ent) 12429 return snprintf(buf, size, "%u", idx); 12430 ++nb; 12431 } 12432 return nb; 12433 } 12434 12435 /** Complete index number for set raw_ipv6_ext_push/ipv6_ext_remove commands. */ 12436 static int 12437 comp_set_ipv6_ext_index(struct context *ctx, const struct token *token, 12438 unsigned int ent, char *buf, unsigned int size) 12439 { 12440 uint16_t idx = 0; 12441 uint16_t nb = 0; 12442 12443 RTE_SET_USED(ctx); 12444 RTE_SET_USED(token); 12445 for (idx = 0; idx < IPV6_EXT_PUSH_CONFS_MAX_NUM; ++idx) { 12446 if (buf && idx == ent) 12447 return snprintf(buf, size, "%u", idx); 12448 ++nb; 12449 } 12450 return nb; 12451 } 12452 12453 /** Complete index number for set raw_encap/raw_decap commands. */ 12454 static int 12455 comp_set_sample_index(struct context *ctx, const struct token *token, 12456 unsigned int ent, char *buf, unsigned int size) 12457 { 12458 uint16_t idx = 0; 12459 uint16_t nb = 0; 12460 12461 RTE_SET_USED(ctx); 12462 RTE_SET_USED(token); 12463 for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) { 12464 if (buf && idx == ent) 12465 return snprintf(buf, size, "%u", idx); 12466 ++nb; 12467 } 12468 return nb; 12469 } 12470 12471 /** Complete operation for modify_field command. */ 12472 static int 12473 comp_set_modify_field_op(struct context *ctx, const struct token *token, 12474 unsigned int ent, char *buf, unsigned int size) 12475 { 12476 RTE_SET_USED(ctx); 12477 RTE_SET_USED(token); 12478 if (!buf) 12479 return RTE_DIM(modify_field_ops); 12480 if (ent < RTE_DIM(modify_field_ops) - 1) 12481 return strlcpy(buf, modify_field_ops[ent], size); 12482 return -1; 12483 } 12484 12485 /** Complete field id for modify_field command. */ 12486 static int 12487 comp_set_modify_field_id(struct context *ctx, const struct token *token, 12488 unsigned int ent, char *buf, unsigned int size) 12489 { 12490 const char *name; 12491 12492 RTE_SET_USED(token); 12493 if (!buf) 12494 return RTE_DIM(flow_field_ids); 12495 if (ent >= RTE_DIM(flow_field_ids) - 1) 12496 return -1; 12497 name = flow_field_ids[ent]; 12498 if (ctx->curr == ACTION_MODIFY_FIELD_SRC_TYPE || 12499 (strcmp(name, "pointer") && strcmp(name, "value"))) 12500 return strlcpy(buf, name, size); 12501 return -1; 12502 } 12503 12504 /** Complete available pattern template IDs. */ 12505 static int 12506 comp_pattern_template_id(struct context *ctx, const struct token *token, 12507 unsigned int ent, char *buf, unsigned int size) 12508 { 12509 unsigned int i = 0; 12510 struct rte_port *port; 12511 struct port_template *pt; 12512 12513 (void)token; 12514 if (port_id_is_invalid(ctx->port, DISABLED_WARN) || 12515 ctx->port == (portid_t)RTE_PORT_ALL) 12516 return -1; 12517 port = &ports[ctx->port]; 12518 for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) { 12519 if (buf && i == ent) 12520 return snprintf(buf, size, "%u", pt->id); 12521 ++i; 12522 } 12523 if (buf) 12524 return -1; 12525 return i; 12526 } 12527 12528 /** Complete available actions template IDs. */ 12529 static int 12530 comp_actions_template_id(struct context *ctx, const struct token *token, 12531 unsigned int ent, char *buf, unsigned int size) 12532 { 12533 unsigned int i = 0; 12534 struct rte_port *port; 12535 struct port_template *pt; 12536 12537 (void)token; 12538 if (port_id_is_invalid(ctx->port, DISABLED_WARN) || 12539 ctx->port == (portid_t)RTE_PORT_ALL) 12540 return -1; 12541 port = &ports[ctx->port]; 12542 for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) { 12543 if (buf && i == ent) 12544 return snprintf(buf, size, "%u", pt->id); 12545 ++i; 12546 } 12547 if (buf) 12548 return -1; 12549 return i; 12550 } 12551 12552 /** Complete available table IDs. */ 12553 static int 12554 comp_table_id(struct context *ctx, const struct token *token, 12555 unsigned int ent, char *buf, unsigned int size) 12556 { 12557 unsigned int i = 0; 12558 struct rte_port *port; 12559 struct port_table *pt; 12560 12561 (void)token; 12562 if (port_id_is_invalid(ctx->port, DISABLED_WARN) || 12563 ctx->port == (portid_t)RTE_PORT_ALL) 12564 return -1; 12565 port = &ports[ctx->port]; 12566 for (pt = port->table_list; pt != NULL; pt = pt->next) { 12567 if (buf && i == ent) 12568 return snprintf(buf, size, "%u", pt->id); 12569 ++i; 12570 } 12571 if (buf) 12572 return -1; 12573 return i; 12574 } 12575 12576 /** Complete available queue IDs. */ 12577 static int 12578 comp_queue_id(struct context *ctx, const struct token *token, 12579 unsigned int ent, char *buf, unsigned int size) 12580 { 12581 unsigned int i = 0; 12582 struct rte_port *port; 12583 12584 (void)token; 12585 if (port_id_is_invalid(ctx->port, DISABLED_WARN) || 12586 ctx->port == (portid_t)RTE_PORT_ALL) 12587 return -1; 12588 port = &ports[ctx->port]; 12589 for (i = 0; i < port->queue_nb; i++) { 12590 if (buf && i == ent) 12591 return snprintf(buf, size, "%u", i); 12592 } 12593 if (buf) 12594 return -1; 12595 return i; 12596 } 12597 12598 static int 12599 comp_names_to_index(struct context *ctx, const struct token *token, 12600 unsigned int ent, char *buf, unsigned int size, 12601 const char *const names[], size_t names_size) 12602 { 12603 RTE_SET_USED(ctx); 12604 RTE_SET_USED(token); 12605 if (!buf) 12606 return names_size; 12607 if (names[ent] && ent < names_size) 12608 return rte_strscpy(buf, names[ent], size); 12609 return -1; 12610 12611 } 12612 12613 /** Complete available Meter colors. */ 12614 static int 12615 comp_meter_color(struct context *ctx, const struct token *token, 12616 unsigned int ent, char *buf, unsigned int size) 12617 { 12618 RTE_SET_USED(ctx); 12619 RTE_SET_USED(token); 12620 if (!buf) 12621 return RTE_DIM(meter_colors); 12622 if (ent < RTE_DIM(meter_colors) - 1) 12623 return strlcpy(buf, meter_colors[ent], size); 12624 return -1; 12625 } 12626 12627 /** Complete available Insertion Table types. */ 12628 static int 12629 comp_insertion_table_type(struct context *ctx, const struct token *token, 12630 unsigned int ent, char *buf, unsigned int size) 12631 { 12632 RTE_SET_USED(ctx); 12633 RTE_SET_USED(token); 12634 if (!buf) 12635 return RTE_DIM(table_insertion_types); 12636 if (ent < RTE_DIM(table_insertion_types) - 1) 12637 return rte_strscpy(buf, table_insertion_types[ent], size); 12638 return -1; 12639 } 12640 12641 /** Complete available Hash Calculation Table types. */ 12642 static int 12643 comp_hash_table_type(struct context *ctx, const struct token *token, 12644 unsigned int ent, char *buf, unsigned int size) 12645 { 12646 RTE_SET_USED(ctx); 12647 RTE_SET_USED(token); 12648 if (!buf) 12649 return RTE_DIM(table_hash_funcs); 12650 if (ent < RTE_DIM(table_hash_funcs) - 1) 12651 return rte_strscpy(buf, table_hash_funcs[ent], size); 12652 return -1; 12653 } 12654 12655 static int 12656 comp_quota_state_name(struct context *ctx, const struct token *token, 12657 unsigned int ent, char *buf, unsigned int size) 12658 { 12659 return comp_names_to_index(ctx, token, ent, buf, size, 12660 quota_state_names, 12661 RTE_DIM(quota_state_names)); 12662 } 12663 12664 static int 12665 comp_quota_mode_name(struct context *ctx, const struct token *token, 12666 unsigned int ent, char *buf, unsigned int size) 12667 { 12668 return comp_names_to_index(ctx, token, ent, buf, size, 12669 quota_mode_names, 12670 RTE_DIM(quota_mode_names)); 12671 } 12672 12673 static int 12674 comp_quota_update_name(struct context *ctx, const struct token *token, 12675 unsigned int ent, char *buf, unsigned int size) 12676 { 12677 return comp_names_to_index(ctx, token, ent, buf, size, 12678 quota_update_names, 12679 RTE_DIM(quota_update_names)); 12680 } 12681 12682 static int 12683 comp_qu_mode_name(struct context *ctx, const struct token *token, 12684 unsigned int ent, char *buf, unsigned int size) 12685 { 12686 return comp_names_to_index(ctx, token, ent, buf, size, 12687 query_update_mode_names, 12688 RTE_DIM(query_update_mode_names)); 12689 } 12690 12691 /** Internal context. */ 12692 static struct context cmd_flow_context; 12693 12694 /** Global parser instance (cmdline API). */ 12695 cmdline_parse_inst_t cmd_flow; 12696 cmdline_parse_inst_t cmd_set_raw; 12697 12698 /** Initialize context. */ 12699 static void 12700 cmd_flow_context_init(struct context *ctx) 12701 { 12702 /* A full memset() is not necessary. */ 12703 ctx->curr = ZERO; 12704 ctx->prev = ZERO; 12705 ctx->next_num = 0; 12706 ctx->args_num = 0; 12707 ctx->eol = 0; 12708 ctx->last = 0; 12709 ctx->port = 0; 12710 ctx->objdata = 0; 12711 ctx->object = NULL; 12712 ctx->objmask = NULL; 12713 } 12714 12715 /** Parse a token (cmdline API). */ 12716 static int 12717 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result, 12718 unsigned int size) 12719 { 12720 struct context *ctx = &cmd_flow_context; 12721 const struct token *token; 12722 const enum index *list; 12723 int len; 12724 int i; 12725 12726 (void)hdr; 12727 token = &token_list[ctx->curr]; 12728 /* Check argument length. */ 12729 ctx->eol = 0; 12730 ctx->last = 1; 12731 for (len = 0; src[len]; ++len) 12732 if (src[len] == '#' || isspace(src[len])) 12733 break; 12734 if (!len) 12735 return -1; 12736 /* Last argument and EOL detection. */ 12737 for (i = len; src[i]; ++i) 12738 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n') 12739 break; 12740 else if (!isspace(src[i])) { 12741 ctx->last = 0; 12742 break; 12743 } 12744 for (; src[i]; ++i) 12745 if (src[i] == '\r' || src[i] == '\n') { 12746 ctx->eol = 1; 12747 break; 12748 } 12749 /* Initialize context if necessary. */ 12750 if (!ctx->next_num) { 12751 if (!token->next) 12752 return 0; 12753 ctx->next[ctx->next_num++] = token->next[0]; 12754 } 12755 /* Process argument through candidates. */ 12756 ctx->prev = ctx->curr; 12757 list = ctx->next[ctx->next_num - 1]; 12758 for (i = 0; list[i]; ++i) { 12759 const struct token *next = &token_list[list[i]]; 12760 int tmp; 12761 12762 ctx->curr = list[i]; 12763 if (next->call) 12764 tmp = next->call(ctx, next, src, len, result, size); 12765 else 12766 tmp = parse_default(ctx, next, src, len, result, size); 12767 if (tmp == -1 || tmp != len) 12768 continue; 12769 token = next; 12770 break; 12771 } 12772 if (!list[i]) 12773 return -1; 12774 --ctx->next_num; 12775 /* Push subsequent tokens if any. */ 12776 if (token->next) 12777 for (i = 0; token->next[i]; ++i) { 12778 if (ctx->next_num == RTE_DIM(ctx->next)) 12779 return -1; 12780 ctx->next[ctx->next_num++] = token->next[i]; 12781 } 12782 /* Push arguments if any. */ 12783 if (token->args) 12784 for (i = 0; token->args[i]; ++i) { 12785 if (ctx->args_num == RTE_DIM(ctx->args)) 12786 return -1; 12787 ctx->args[ctx->args_num++] = token->args[i]; 12788 } 12789 return len; 12790 } 12791 12792 int 12793 flow_parse(const char *src, void *result, unsigned int size, 12794 struct rte_flow_attr **attr, 12795 struct rte_flow_item **pattern, struct rte_flow_action **actions) 12796 { 12797 int ret; 12798 struct context saved_flow_ctx = cmd_flow_context; 12799 12800 cmd_flow_context_init(&cmd_flow_context); 12801 do { 12802 ret = cmd_flow_parse(NULL, src, result, size); 12803 if (ret > 0) { 12804 src += ret; 12805 while (isspace(*src)) 12806 src++; 12807 } 12808 } while (ret > 0 && strlen(src)); 12809 cmd_flow_context = saved_flow_ctx; 12810 *attr = &((struct buffer *)result)->args.vc.attr; 12811 *pattern = ((struct buffer *)result)->args.vc.pattern; 12812 *actions = ((struct buffer *)result)->args.vc.actions; 12813 return (ret >= 0 && !strlen(src)) ? 0 : -1; 12814 } 12815 12816 /** Return number of completion entries (cmdline API). */ 12817 static int 12818 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr) 12819 { 12820 struct context *ctx = &cmd_flow_context; 12821 const struct token *token = &token_list[ctx->curr]; 12822 const enum index *list; 12823 int i; 12824 12825 (void)hdr; 12826 /* Count number of tokens in current list. */ 12827 if (ctx->next_num) 12828 list = ctx->next[ctx->next_num - 1]; 12829 else 12830 list = token->next[0]; 12831 for (i = 0; list[i]; ++i) 12832 ; 12833 if (!i) 12834 return 0; 12835 /* 12836 * If there is a single token, use its completion callback, otherwise 12837 * return the number of entries. 12838 */ 12839 token = &token_list[list[0]]; 12840 if (i == 1 && token->comp) { 12841 /* Save index for cmd_flow_get_help(). */ 12842 ctx->prev = list[0]; 12843 return token->comp(ctx, token, 0, NULL, 0); 12844 } 12845 return i; 12846 } 12847 12848 /** Return a completion entry (cmdline API). */ 12849 static int 12850 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index, 12851 char *dst, unsigned int size) 12852 { 12853 struct context *ctx = &cmd_flow_context; 12854 const struct token *token = &token_list[ctx->curr]; 12855 const enum index *list; 12856 int i; 12857 12858 (void)hdr; 12859 /* Count number of tokens in current list. */ 12860 if (ctx->next_num) 12861 list = ctx->next[ctx->next_num - 1]; 12862 else 12863 list = token->next[0]; 12864 for (i = 0; list[i]; ++i) 12865 ; 12866 if (!i) 12867 return -1; 12868 /* If there is a single token, use its completion callback. */ 12869 token = &token_list[list[0]]; 12870 if (i == 1 && token->comp) { 12871 /* Save index for cmd_flow_get_help(). */ 12872 ctx->prev = list[0]; 12873 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0; 12874 } 12875 /* Otherwise make sure the index is valid and use defaults. */ 12876 if (index >= i) 12877 return -1; 12878 token = &token_list[list[index]]; 12879 strlcpy(dst, token->name, size); 12880 /* Save index for cmd_flow_get_help(). */ 12881 ctx->prev = list[index]; 12882 return 0; 12883 } 12884 12885 /** Populate help strings for current token (cmdline API). */ 12886 static int 12887 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size) 12888 { 12889 struct context *ctx = &cmd_flow_context; 12890 const struct token *token = &token_list[ctx->prev]; 12891 12892 (void)hdr; 12893 if (!size) 12894 return -1; 12895 /* Set token type and update global help with details. */ 12896 strlcpy(dst, (token->type ? token->type : "TOKEN"), size); 12897 if (token->help) 12898 cmd_flow.help_str = token->help; 12899 else 12900 cmd_flow.help_str = token->name; 12901 return 0; 12902 } 12903 12904 /** Token definition template (cmdline API). */ 12905 static struct cmdline_token_hdr cmd_flow_token_hdr = { 12906 .ops = &(struct cmdline_token_ops){ 12907 .parse = cmd_flow_parse, 12908 .complete_get_nb = cmd_flow_complete_get_nb, 12909 .complete_get_elt = cmd_flow_complete_get_elt, 12910 .get_help = cmd_flow_get_help, 12911 }, 12912 .offset = 0, 12913 }; 12914 12915 /** Populate the next dynamic token. */ 12916 static void 12917 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr, 12918 cmdline_parse_token_hdr_t **hdr_inst) 12919 { 12920 struct context *ctx = &cmd_flow_context; 12921 12922 /* Always reinitialize context before requesting the first token. */ 12923 if (!(hdr_inst - cmd_flow.tokens)) 12924 cmd_flow_context_init(ctx); 12925 /* Return NULL when no more tokens are expected. */ 12926 if (!ctx->next_num && ctx->curr) { 12927 *hdr = NULL; 12928 return; 12929 } 12930 /* Determine if command should end here. */ 12931 if (ctx->eol && ctx->last && ctx->next_num) { 12932 const enum index *list = ctx->next[ctx->next_num - 1]; 12933 int i; 12934 12935 for (i = 0; list[i]; ++i) { 12936 if (list[i] != END) 12937 continue; 12938 *hdr = NULL; 12939 return; 12940 } 12941 } 12942 *hdr = &cmd_flow_token_hdr; 12943 } 12944 12945 static SLIST_HEAD(, indlst_conf) indlst_conf_head = 12946 SLIST_HEAD_INITIALIZER(); 12947 12948 static void 12949 indirect_action_flow_conf_create(const struct buffer *in) 12950 { 12951 int len, ret; 12952 uint32_t i; 12953 struct indlst_conf *indlst_conf = NULL; 12954 size_t base = RTE_ALIGN(sizeof(*indlst_conf), 8); 12955 struct rte_flow_action *src = in->args.vc.actions; 12956 12957 if (!in->args.vc.actions_n) 12958 goto end; 12959 len = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, NULL, 0, src, NULL); 12960 if (len <= 0) 12961 goto end; 12962 len = RTE_ALIGN(len, 16); 12963 12964 indlst_conf = calloc(1, base + len + 12965 in->args.vc.actions_n * sizeof(uintptr_t)); 12966 if (!indlst_conf) 12967 goto end; 12968 indlst_conf->id = in->args.vc.attr.group; 12969 indlst_conf->conf_num = in->args.vc.actions_n - 1; 12970 indlst_conf->actions = RTE_PTR_ADD(indlst_conf, base); 12971 ret = rte_flow_conv(RTE_FLOW_CONV_OP_ACTIONS, indlst_conf->actions, 12972 len, src, NULL); 12973 if (ret <= 0) { 12974 free(indlst_conf); 12975 indlst_conf = NULL; 12976 goto end; 12977 } 12978 indlst_conf->conf = RTE_PTR_ADD(indlst_conf, base + len); 12979 for (i = 0; i < indlst_conf->conf_num; i++) 12980 indlst_conf->conf[i] = indlst_conf->actions[i].conf; 12981 SLIST_INSERT_HEAD(&indlst_conf_head, indlst_conf, next); 12982 end: 12983 if (indlst_conf) 12984 printf("created indirect action list configuration %u\n", 12985 in->args.vc.attr.group); 12986 else 12987 printf("cannot create indirect action list configuration %u\n", 12988 in->args.vc.attr.group); 12989 } 12990 12991 static const struct indlst_conf * 12992 indirect_action_list_conf_get(uint32_t conf_id) 12993 { 12994 const struct indlst_conf *conf; 12995 12996 SLIST_FOREACH(conf, &indlst_conf_head, next) { 12997 if (conf->id == conf_id) 12998 return conf; 12999 } 13000 return NULL; 13001 } 13002 13003 /** Dispatch parsed buffer to function calls. */ 13004 static void 13005 cmd_flow_parsed(const struct buffer *in) 13006 { 13007 switch (in->command) { 13008 case INFO: 13009 port_flow_get_info(in->port); 13010 break; 13011 case CONFIGURE: 13012 port_flow_configure(in->port, 13013 &in->args.configure.port_attr, 13014 in->args.configure.nb_queue, 13015 &in->args.configure.queue_attr); 13016 break; 13017 case PATTERN_TEMPLATE_CREATE: 13018 port_flow_pattern_template_create(in->port, 13019 in->args.vc.pat_templ_id, 13020 &((const struct rte_flow_pattern_template_attr) { 13021 .relaxed_matching = in->args.vc.attr.reserved, 13022 .ingress = in->args.vc.attr.ingress, 13023 .egress = in->args.vc.attr.egress, 13024 .transfer = in->args.vc.attr.transfer, 13025 }), 13026 in->args.vc.pattern); 13027 break; 13028 case PATTERN_TEMPLATE_DESTROY: 13029 port_flow_pattern_template_destroy(in->port, 13030 in->args.templ_destroy.template_id_n, 13031 in->args.templ_destroy.template_id); 13032 break; 13033 case ACTIONS_TEMPLATE_CREATE: 13034 port_flow_actions_template_create(in->port, 13035 in->args.vc.act_templ_id, 13036 &((const struct rte_flow_actions_template_attr) { 13037 .ingress = in->args.vc.attr.ingress, 13038 .egress = in->args.vc.attr.egress, 13039 .transfer = in->args.vc.attr.transfer, 13040 }), 13041 in->args.vc.actions, 13042 in->args.vc.masks); 13043 break; 13044 case ACTIONS_TEMPLATE_DESTROY: 13045 port_flow_actions_template_destroy(in->port, 13046 in->args.templ_destroy.template_id_n, 13047 in->args.templ_destroy.template_id); 13048 break; 13049 case TABLE_CREATE: 13050 port_flow_template_table_create(in->port, in->args.table.id, 13051 &in->args.table.attr, in->args.table.pat_templ_id_n, 13052 in->args.table.pat_templ_id, in->args.table.act_templ_id_n, 13053 in->args.table.act_templ_id); 13054 break; 13055 case TABLE_DESTROY: 13056 port_flow_template_table_destroy(in->port, 13057 in->args.table_destroy.table_id_n, 13058 in->args.table_destroy.table_id); 13059 break; 13060 case GROUP_SET_MISS_ACTIONS: 13061 port_queue_group_set_miss_actions(in->port, &in->args.vc.attr, 13062 in->args.vc.actions); 13063 break; 13064 case QUEUE_CREATE: 13065 port_queue_flow_create(in->port, in->queue, in->postpone, 13066 in->args.vc.table_id, in->args.vc.rule_id, 13067 in->args.vc.pat_templ_id, in->args.vc.act_templ_id, 13068 in->args.vc.pattern, in->args.vc.actions); 13069 break; 13070 case QUEUE_DESTROY: 13071 port_queue_flow_destroy(in->port, in->queue, in->postpone, 13072 in->args.destroy.rule_n, 13073 in->args.destroy.rule); 13074 break; 13075 case QUEUE_UPDATE: 13076 port_queue_flow_update(in->port, in->queue, in->postpone, 13077 in->args.vc.rule_id, in->args.vc.act_templ_id, 13078 in->args.vc.actions); 13079 break; 13080 case PUSH: 13081 port_queue_flow_push(in->port, in->queue); 13082 break; 13083 case PULL: 13084 port_queue_flow_pull(in->port, in->queue); 13085 break; 13086 case HASH: 13087 if (!in->args.vc.encap_hash) 13088 port_flow_hash_calc(in->port, in->args.vc.table_id, 13089 in->args.vc.pat_templ_id, 13090 in->args.vc.pattern); 13091 else 13092 port_flow_hash_calc_encap(in->port, in->args.vc.field, 13093 in->args.vc.pattern); 13094 break; 13095 case QUEUE_AGED: 13096 port_queue_flow_aged(in->port, in->queue, 13097 in->args.aged.destroy); 13098 break; 13099 case QUEUE_INDIRECT_ACTION_CREATE: 13100 case QUEUE_INDIRECT_ACTION_LIST_CREATE: 13101 port_queue_action_handle_create( 13102 in->port, in->queue, in->postpone, 13103 in->args.vc.attr.group, 13104 &((const struct rte_flow_indir_action_conf) { 13105 .ingress = in->args.vc.attr.ingress, 13106 .egress = in->args.vc.attr.egress, 13107 .transfer = in->args.vc.attr.transfer, 13108 }), 13109 in->args.vc.actions); 13110 break; 13111 case QUEUE_INDIRECT_ACTION_DESTROY: 13112 port_queue_action_handle_destroy(in->port, 13113 in->queue, in->postpone, 13114 in->args.ia_destroy.action_id_n, 13115 in->args.ia_destroy.action_id); 13116 break; 13117 case QUEUE_INDIRECT_ACTION_UPDATE: 13118 port_queue_action_handle_update(in->port, 13119 in->queue, in->postpone, 13120 in->args.vc.attr.group, 13121 in->args.vc.actions); 13122 break; 13123 case QUEUE_INDIRECT_ACTION_QUERY: 13124 port_queue_action_handle_query(in->port, 13125 in->queue, in->postpone, 13126 in->args.ia.action_id); 13127 break; 13128 case QUEUE_INDIRECT_ACTION_QUERY_UPDATE: 13129 port_queue_action_handle_query_update(in->port, in->queue, 13130 in->postpone, 13131 in->args.ia.action_id, 13132 in->args.ia.qu_mode, 13133 in->args.vc.actions); 13134 break; 13135 case INDIRECT_ACTION_CREATE: 13136 case INDIRECT_ACTION_LIST_CREATE: 13137 port_action_handle_create( 13138 in->port, in->args.vc.attr.group, 13139 in->command == INDIRECT_ACTION_LIST_CREATE, 13140 &((const struct rte_flow_indir_action_conf) { 13141 .ingress = in->args.vc.attr.ingress, 13142 .egress = in->args.vc.attr.egress, 13143 .transfer = in->args.vc.attr.transfer, 13144 }), 13145 in->args.vc.actions); 13146 break; 13147 case INDIRECT_ACTION_FLOW_CONF_CREATE: 13148 indirect_action_flow_conf_create(in); 13149 break; 13150 case INDIRECT_ACTION_DESTROY: 13151 port_action_handle_destroy(in->port, 13152 in->args.ia_destroy.action_id_n, 13153 in->args.ia_destroy.action_id); 13154 break; 13155 case INDIRECT_ACTION_UPDATE: 13156 port_action_handle_update(in->port, in->args.vc.attr.group, 13157 in->args.vc.actions); 13158 break; 13159 case INDIRECT_ACTION_QUERY: 13160 port_action_handle_query(in->port, in->args.ia.action_id); 13161 break; 13162 case INDIRECT_ACTION_QUERY_UPDATE: 13163 port_action_handle_query_update(in->port, 13164 in->args.ia.action_id, 13165 in->args.ia.qu_mode, 13166 in->args.vc.actions); 13167 break; 13168 case VALIDATE: 13169 port_flow_validate(in->port, &in->args.vc.attr, 13170 in->args.vc.pattern, in->args.vc.actions, 13171 &in->args.vc.tunnel_ops); 13172 break; 13173 case CREATE: 13174 port_flow_create(in->port, &in->args.vc.attr, 13175 in->args.vc.pattern, in->args.vc.actions, 13176 &in->args.vc.tunnel_ops, in->args.vc.user_id); 13177 break; 13178 case DESTROY: 13179 port_flow_destroy(in->port, in->args.destroy.rule_n, 13180 in->args.destroy.rule, 13181 in->args.destroy.is_user_id); 13182 break; 13183 case FLUSH: 13184 port_flow_flush(in->port); 13185 break; 13186 case DUMP_ONE: 13187 case DUMP_ALL: 13188 port_flow_dump(in->port, in->args.dump.mode, 13189 in->args.dump.rule, in->args.dump.file, 13190 in->args.dump.is_user_id); 13191 break; 13192 case QUERY: 13193 port_flow_query(in->port, in->args.query.rule, 13194 &in->args.query.action, 13195 in->args.query.is_user_id); 13196 break; 13197 case LIST: 13198 port_flow_list(in->port, in->args.list.group_n, 13199 in->args.list.group); 13200 break; 13201 case ISOLATE: 13202 port_flow_isolate(in->port, in->args.isolate.set); 13203 break; 13204 case AGED: 13205 port_flow_aged(in->port, in->args.aged.destroy); 13206 break; 13207 case TUNNEL_CREATE: 13208 port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops); 13209 break; 13210 case TUNNEL_DESTROY: 13211 port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id); 13212 break; 13213 case TUNNEL_LIST: 13214 port_flow_tunnel_list(in->port); 13215 break; 13216 case ACTION_POL_G: 13217 port_meter_policy_add(in->port, in->args.policy.policy_id, 13218 in->args.vc.actions); 13219 break; 13220 case FLEX_ITEM_CREATE: 13221 flex_item_create(in->port, in->args.flex.token, 13222 in->args.flex.filename); 13223 break; 13224 case FLEX_ITEM_DESTROY: 13225 flex_item_destroy(in->port, in->args.flex.token); 13226 break; 13227 default: 13228 break; 13229 } 13230 fflush(stdout); 13231 } 13232 13233 /** Token generator and output processing callback (cmdline API). */ 13234 static void 13235 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2) 13236 { 13237 if (cl == NULL) 13238 cmd_flow_tok(arg0, arg2); 13239 else 13240 cmd_flow_parsed(arg0); 13241 } 13242 13243 /** Global parser instance (cmdline API). */ 13244 cmdline_parse_inst_t cmd_flow = { 13245 .f = cmd_flow_cb, 13246 .data = NULL, /**< Unused. */ 13247 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */ 13248 .tokens = { 13249 NULL, 13250 }, /**< Tokens are returned by cmd_flow_tok(). */ 13251 }; 13252 13253 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */ 13254 13255 static void 13256 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto) 13257 { 13258 struct rte_ipv4_hdr *ipv4; 13259 struct rte_ether_hdr *eth; 13260 struct rte_ipv6_hdr *ipv6; 13261 struct rte_vxlan_hdr *vxlan; 13262 struct rte_vxlan_gpe_hdr *gpe; 13263 struct rte_flow_item_nvgre *nvgre; 13264 uint32_t ipv6_vtc_flow; 13265 13266 switch (item->type) { 13267 case RTE_FLOW_ITEM_TYPE_ETH: 13268 eth = (struct rte_ether_hdr *)buf; 13269 if (next_proto) 13270 eth->ether_type = rte_cpu_to_be_16(next_proto); 13271 break; 13272 case RTE_FLOW_ITEM_TYPE_IPV4: 13273 ipv4 = (struct rte_ipv4_hdr *)buf; 13274 if (!ipv4->version_ihl) 13275 ipv4->version_ihl = RTE_IPV4_VHL_DEF; 13276 if (next_proto && ipv4->next_proto_id == 0) 13277 ipv4->next_proto_id = (uint8_t)next_proto; 13278 break; 13279 case RTE_FLOW_ITEM_TYPE_IPV6: 13280 ipv6 = (struct rte_ipv6_hdr *)buf; 13281 if (next_proto && ipv6->proto == 0) 13282 ipv6->proto = (uint8_t)next_proto; 13283 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->vtc_flow); 13284 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */ 13285 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */ 13286 ipv6->vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow); 13287 break; 13288 case RTE_FLOW_ITEM_TYPE_VXLAN: 13289 vxlan = (struct rte_vxlan_hdr *)buf; 13290 vxlan->vx_flags = 0x08; 13291 break; 13292 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 13293 gpe = (struct rte_vxlan_gpe_hdr *)buf; 13294 gpe->vx_flags = 0x0C; 13295 break; 13296 case RTE_FLOW_ITEM_TYPE_NVGRE: 13297 nvgre = (struct rte_flow_item_nvgre *)buf; 13298 nvgre->protocol = rte_cpu_to_be_16(0x6558); 13299 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000); 13300 break; 13301 default: 13302 break; 13303 } 13304 } 13305 13306 /** Helper of get item's default mask. */ 13307 static const void * 13308 flow_item_default_mask(const struct rte_flow_item *item) 13309 { 13310 const void *mask = NULL; 13311 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX); 13312 static struct rte_flow_item_ipv6_routing_ext ipv6_routing_ext_default_mask = { 13313 .hdr = { 13314 .next_hdr = 0xff, 13315 .type = 0xff, 13316 .segments_left = 0xff, 13317 }, 13318 }; 13319 13320 switch (item->type) { 13321 case RTE_FLOW_ITEM_TYPE_ANY: 13322 mask = &rte_flow_item_any_mask; 13323 break; 13324 case RTE_FLOW_ITEM_TYPE_PORT_ID: 13325 mask = &rte_flow_item_port_id_mask; 13326 break; 13327 case RTE_FLOW_ITEM_TYPE_RAW: 13328 mask = &rte_flow_item_raw_mask; 13329 break; 13330 case RTE_FLOW_ITEM_TYPE_ETH: 13331 mask = &rte_flow_item_eth_mask; 13332 break; 13333 case RTE_FLOW_ITEM_TYPE_VLAN: 13334 mask = &rte_flow_item_vlan_mask; 13335 break; 13336 case RTE_FLOW_ITEM_TYPE_IPV4: 13337 mask = &rte_flow_item_ipv4_mask; 13338 break; 13339 case RTE_FLOW_ITEM_TYPE_IPV6: 13340 mask = &rte_flow_item_ipv6_mask; 13341 break; 13342 case RTE_FLOW_ITEM_TYPE_ICMP: 13343 mask = &rte_flow_item_icmp_mask; 13344 break; 13345 case RTE_FLOW_ITEM_TYPE_UDP: 13346 mask = &rte_flow_item_udp_mask; 13347 break; 13348 case RTE_FLOW_ITEM_TYPE_TCP: 13349 mask = &rte_flow_item_tcp_mask; 13350 break; 13351 case RTE_FLOW_ITEM_TYPE_SCTP: 13352 mask = &rte_flow_item_sctp_mask; 13353 break; 13354 case RTE_FLOW_ITEM_TYPE_VXLAN: 13355 mask = &rte_flow_item_vxlan_mask; 13356 break; 13357 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 13358 mask = &rte_flow_item_vxlan_gpe_mask; 13359 break; 13360 case RTE_FLOW_ITEM_TYPE_E_TAG: 13361 mask = &rte_flow_item_e_tag_mask; 13362 break; 13363 case RTE_FLOW_ITEM_TYPE_NVGRE: 13364 mask = &rte_flow_item_nvgre_mask; 13365 break; 13366 case RTE_FLOW_ITEM_TYPE_MPLS: 13367 mask = &rte_flow_item_mpls_mask; 13368 break; 13369 case RTE_FLOW_ITEM_TYPE_GRE: 13370 mask = &rte_flow_item_gre_mask; 13371 break; 13372 case RTE_FLOW_ITEM_TYPE_GRE_KEY: 13373 mask = &gre_key_default_mask; 13374 break; 13375 case RTE_FLOW_ITEM_TYPE_META: 13376 mask = &rte_flow_item_meta_mask; 13377 break; 13378 case RTE_FLOW_ITEM_TYPE_RANDOM: 13379 mask = &rte_flow_item_random_mask; 13380 break; 13381 case RTE_FLOW_ITEM_TYPE_FUZZY: 13382 mask = &rte_flow_item_fuzzy_mask; 13383 break; 13384 case RTE_FLOW_ITEM_TYPE_GTP: 13385 mask = &rte_flow_item_gtp_mask; 13386 break; 13387 case RTE_FLOW_ITEM_TYPE_GTP_PSC: 13388 mask = &rte_flow_item_gtp_psc_mask; 13389 break; 13390 case RTE_FLOW_ITEM_TYPE_GENEVE: 13391 mask = &rte_flow_item_geneve_mask; 13392 break; 13393 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT: 13394 mask = &rte_flow_item_geneve_opt_mask; 13395 break; 13396 case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID: 13397 mask = &rte_flow_item_pppoe_proto_id_mask; 13398 break; 13399 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP: 13400 mask = &rte_flow_item_l2tpv3oip_mask; 13401 break; 13402 case RTE_FLOW_ITEM_TYPE_ESP: 13403 mask = &rte_flow_item_esp_mask; 13404 break; 13405 case RTE_FLOW_ITEM_TYPE_AH: 13406 mask = &rte_flow_item_ah_mask; 13407 break; 13408 case RTE_FLOW_ITEM_TYPE_PFCP: 13409 mask = &rte_flow_item_pfcp_mask; 13410 break; 13411 case RTE_FLOW_ITEM_TYPE_PORT_REPRESENTOR: 13412 case RTE_FLOW_ITEM_TYPE_REPRESENTED_PORT: 13413 mask = &rte_flow_item_ethdev_mask; 13414 break; 13415 case RTE_FLOW_ITEM_TYPE_L2TPV2: 13416 mask = &rte_flow_item_l2tpv2_mask; 13417 break; 13418 case RTE_FLOW_ITEM_TYPE_PPP: 13419 mask = &rte_flow_item_ppp_mask; 13420 break; 13421 case RTE_FLOW_ITEM_TYPE_METER_COLOR: 13422 mask = &rte_flow_item_meter_color_mask; 13423 break; 13424 case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT: 13425 mask = &ipv6_routing_ext_default_mask; 13426 break; 13427 case RTE_FLOW_ITEM_TYPE_AGGR_AFFINITY: 13428 mask = &rte_flow_item_aggr_affinity_mask; 13429 break; 13430 case RTE_FLOW_ITEM_TYPE_TX_QUEUE: 13431 mask = &rte_flow_item_tx_queue_mask; 13432 break; 13433 case RTE_FLOW_ITEM_TYPE_IB_BTH: 13434 mask = &rte_flow_item_ib_bth_mask; 13435 break; 13436 case RTE_FLOW_ITEM_TYPE_PTYPE: 13437 mask = &rte_flow_item_ptype_mask; 13438 break; 13439 default: 13440 break; 13441 } 13442 return mask; 13443 } 13444 13445 /** Dispatch parsed buffer to function calls. */ 13446 static void 13447 cmd_set_ipv6_ext_parsed(const struct buffer *in) 13448 { 13449 uint32_t n = in->args.vc.pattern_n; 13450 int i = 0; 13451 struct rte_flow_item *item = NULL; 13452 size_t size = 0; 13453 uint8_t *data = NULL; 13454 uint8_t *type = NULL; 13455 size_t *total_size = NULL; 13456 uint16_t idx = in->port; /* We borrow port field as index */ 13457 struct rte_flow_item_ipv6_routing_ext *ext; 13458 const struct rte_flow_item_ipv6_ext *ipv6_ext; 13459 13460 RTE_ASSERT(in->command == SET_IPV6_EXT_PUSH || 13461 in->command == SET_IPV6_EXT_REMOVE); 13462 13463 if (in->command == SET_IPV6_EXT_REMOVE) { 13464 if (n != 1 || in->args.vc.pattern->type != 13465 RTE_FLOW_ITEM_TYPE_IPV6_EXT) { 13466 fprintf(stderr, "Error - Not supported item\n"); 13467 return; 13468 } 13469 type = (uint8_t *)&ipv6_ext_remove_confs[idx].type; 13470 item = in->args.vc.pattern; 13471 ipv6_ext = item->spec; 13472 *type = ipv6_ext->next_hdr; 13473 return; 13474 } 13475 13476 total_size = &ipv6_ext_push_confs[idx].size; 13477 data = (uint8_t *)&ipv6_ext_push_confs[idx].data; 13478 type = (uint8_t *)&ipv6_ext_push_confs[idx].type; 13479 13480 *total_size = 0; 13481 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA); 13482 for (i = n - 1 ; i >= 0; --i) { 13483 item = in->args.vc.pattern + i; 13484 switch (item->type) { 13485 case RTE_FLOW_ITEM_TYPE_IPV6_EXT: 13486 ipv6_ext = item->spec; 13487 *type = ipv6_ext->next_hdr; 13488 break; 13489 case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT: 13490 ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec; 13491 if (!ext->hdr.hdr_len) { 13492 size = sizeof(struct rte_ipv6_routing_ext) + 13493 (ext->hdr.segments_left << 4); 13494 ext->hdr.hdr_len = ext->hdr.segments_left << 1; 13495 /* Indicate no TLV once SRH. */ 13496 if (ext->hdr.type == 4) 13497 ext->hdr.last_entry = ext->hdr.segments_left - 1; 13498 } else { 13499 size = sizeof(struct rte_ipv6_routing_ext) + 13500 (ext->hdr.hdr_len << 3); 13501 } 13502 *total_size += size; 13503 memcpy(data, ext, size); 13504 break; 13505 default: 13506 fprintf(stderr, "Error - Not supported item\n"); 13507 goto error; 13508 } 13509 } 13510 RTE_ASSERT((*total_size) <= ACTION_IPV6_EXT_PUSH_MAX_DATA); 13511 return; 13512 error: 13513 *total_size = 0; 13514 memset(data, 0x00, ACTION_IPV6_EXT_PUSH_MAX_DATA); 13515 } 13516 13517 /** Dispatch parsed buffer to function calls. */ 13518 static void 13519 cmd_set_raw_parsed_sample(const struct buffer *in) 13520 { 13521 uint32_t n = in->args.vc.actions_n; 13522 uint32_t i = 0; 13523 struct rte_flow_action *action = NULL; 13524 struct rte_flow_action *data = NULL; 13525 const struct rte_flow_action_rss *rss = NULL; 13526 size_t size = 0; 13527 uint16_t idx = in->port; /* We borrow port field as index */ 13528 uint32_t max_size = sizeof(struct rte_flow_action) * 13529 ACTION_SAMPLE_ACTIONS_NUM; 13530 13531 RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS); 13532 data = (struct rte_flow_action *)&raw_sample_confs[idx].data; 13533 memset(data, 0x00, max_size); 13534 for (; i <= n - 1; i++) { 13535 action = in->args.vc.actions + i; 13536 if (action->type == RTE_FLOW_ACTION_TYPE_END) 13537 break; 13538 switch (action->type) { 13539 case RTE_FLOW_ACTION_TYPE_MARK: 13540 size = sizeof(struct rte_flow_action_mark); 13541 rte_memcpy(&sample_mark[idx], 13542 (const void *)action->conf, size); 13543 action->conf = &sample_mark[idx]; 13544 break; 13545 case RTE_FLOW_ACTION_TYPE_COUNT: 13546 size = sizeof(struct rte_flow_action_count); 13547 rte_memcpy(&sample_count[idx], 13548 (const void *)action->conf, size); 13549 action->conf = &sample_count[idx]; 13550 break; 13551 case RTE_FLOW_ACTION_TYPE_QUEUE: 13552 size = sizeof(struct rte_flow_action_queue); 13553 rte_memcpy(&sample_queue[idx], 13554 (const void *)action->conf, size); 13555 action->conf = &sample_queue[idx]; 13556 break; 13557 case RTE_FLOW_ACTION_TYPE_RSS: 13558 size = sizeof(struct rte_flow_action_rss); 13559 rss = action->conf; 13560 rte_memcpy(&sample_rss_data[idx].conf, 13561 (const void *)rss, size); 13562 if (rss->key_len && rss->key) { 13563 sample_rss_data[idx].conf.key = 13564 sample_rss_data[idx].key; 13565 rte_memcpy((void *)((uintptr_t) 13566 sample_rss_data[idx].conf.key), 13567 (const void *)rss->key, 13568 sizeof(uint8_t) * rss->key_len); 13569 } 13570 if (rss->queue_num && rss->queue) { 13571 sample_rss_data[idx].conf.queue = 13572 sample_rss_data[idx].queue; 13573 rte_memcpy((void *)((uintptr_t) 13574 sample_rss_data[idx].conf.queue), 13575 (const void *)rss->queue, 13576 sizeof(uint16_t) * rss->queue_num); 13577 } 13578 action->conf = &sample_rss_data[idx].conf; 13579 break; 13580 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 13581 size = sizeof(struct rte_flow_action_raw_encap); 13582 rte_memcpy(&sample_encap[idx], 13583 (const void *)action->conf, size); 13584 action->conf = &sample_encap[idx]; 13585 break; 13586 case RTE_FLOW_ACTION_TYPE_PORT_ID: 13587 size = sizeof(struct rte_flow_action_port_id); 13588 rte_memcpy(&sample_port_id[idx], 13589 (const void *)action->conf, size); 13590 action->conf = &sample_port_id[idx]; 13591 break; 13592 case RTE_FLOW_ACTION_TYPE_PF: 13593 break; 13594 case RTE_FLOW_ACTION_TYPE_VF: 13595 size = sizeof(struct rte_flow_action_vf); 13596 rte_memcpy(&sample_vf[idx], 13597 (const void *)action->conf, size); 13598 action->conf = &sample_vf[idx]; 13599 break; 13600 case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: 13601 size = sizeof(struct rte_flow_action_vxlan_encap); 13602 parse_setup_vxlan_encap_data(&sample_vxlan_encap[idx]); 13603 action->conf = &sample_vxlan_encap[idx].conf; 13604 break; 13605 case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP: 13606 size = sizeof(struct rte_flow_action_nvgre_encap); 13607 parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]); 13608 action->conf = &sample_nvgre_encap[idx]; 13609 break; 13610 case RTE_FLOW_ACTION_TYPE_PORT_REPRESENTOR: 13611 size = sizeof(struct rte_flow_action_ethdev); 13612 rte_memcpy(&sample_port_representor[idx], 13613 (const void *)action->conf, size); 13614 action->conf = &sample_port_representor[idx]; 13615 break; 13616 case RTE_FLOW_ACTION_TYPE_REPRESENTED_PORT: 13617 size = sizeof(struct rte_flow_action_ethdev); 13618 rte_memcpy(&sample_represented_port[idx], 13619 (const void *)action->conf, size); 13620 action->conf = &sample_represented_port[idx]; 13621 break; 13622 default: 13623 fprintf(stderr, "Error - Not supported action\n"); 13624 return; 13625 } 13626 rte_memcpy(data, action, sizeof(struct rte_flow_action)); 13627 data++; 13628 } 13629 } 13630 13631 /** Dispatch parsed buffer to function calls. */ 13632 static void 13633 cmd_set_raw_parsed(const struct buffer *in) 13634 { 13635 uint32_t n = in->args.vc.pattern_n; 13636 int i = 0; 13637 struct rte_flow_item *item = NULL; 13638 size_t size = 0; 13639 uint8_t *data = NULL; 13640 uint8_t *data_tail = NULL; 13641 size_t *total_size = NULL; 13642 uint16_t upper_layer = 0; 13643 uint16_t proto = 0; 13644 uint16_t idx = in->port; /* We borrow port field as index */ 13645 int gtp_psc = -1; /* GTP PSC option index. */ 13646 const void *src_spec; 13647 13648 if (in->command == SET_SAMPLE_ACTIONS) 13649 return cmd_set_raw_parsed_sample(in); 13650 else if (in->command == SET_IPV6_EXT_PUSH || 13651 in->command == SET_IPV6_EXT_REMOVE) 13652 return cmd_set_ipv6_ext_parsed(in); 13653 RTE_ASSERT(in->command == SET_RAW_ENCAP || 13654 in->command == SET_RAW_DECAP); 13655 if (in->command == SET_RAW_ENCAP) { 13656 total_size = &raw_encap_confs[idx].size; 13657 data = (uint8_t *)&raw_encap_confs[idx].data; 13658 } else { 13659 total_size = &raw_decap_confs[idx].size; 13660 data = (uint8_t *)&raw_decap_confs[idx].data; 13661 } 13662 *total_size = 0; 13663 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA); 13664 /* process hdr from upper layer to low layer (L3/L4 -> L2). */ 13665 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA; 13666 for (i = n - 1 ; i >= 0; --i) { 13667 const struct rte_flow_item_gtp *gtp; 13668 const struct rte_flow_item_geneve_opt *opt; 13669 struct rte_flow_item_ipv6_routing_ext *ext; 13670 13671 item = in->args.vc.pattern + i; 13672 if (item->spec == NULL) 13673 item->spec = flow_item_default_mask(item); 13674 src_spec = item->spec; 13675 switch (item->type) { 13676 case RTE_FLOW_ITEM_TYPE_ETH: 13677 size = sizeof(struct rte_ether_hdr); 13678 break; 13679 case RTE_FLOW_ITEM_TYPE_VLAN: 13680 size = sizeof(struct rte_vlan_hdr); 13681 proto = RTE_ETHER_TYPE_VLAN; 13682 break; 13683 case RTE_FLOW_ITEM_TYPE_IPV4: 13684 size = sizeof(struct rte_ipv4_hdr); 13685 proto = RTE_ETHER_TYPE_IPV4; 13686 break; 13687 case RTE_FLOW_ITEM_TYPE_IPV6: 13688 size = sizeof(struct rte_ipv6_hdr); 13689 proto = RTE_ETHER_TYPE_IPV6; 13690 break; 13691 case RTE_FLOW_ITEM_TYPE_IPV6_ROUTING_EXT: 13692 ext = (struct rte_flow_item_ipv6_routing_ext *)(uintptr_t)item->spec; 13693 if (!ext->hdr.hdr_len) { 13694 size = sizeof(struct rte_ipv6_routing_ext) + 13695 (ext->hdr.segments_left << 4); 13696 ext->hdr.hdr_len = ext->hdr.segments_left << 1; 13697 /* SRv6 without TLV. */ 13698 if (ext->hdr.type == RTE_IPV6_SRCRT_TYPE_4) 13699 ext->hdr.last_entry = ext->hdr.segments_left - 1; 13700 } else { 13701 size = sizeof(struct rte_ipv6_routing_ext) + 13702 (ext->hdr.hdr_len << 3); 13703 } 13704 proto = IPPROTO_ROUTING; 13705 break; 13706 case RTE_FLOW_ITEM_TYPE_UDP: 13707 size = sizeof(struct rte_udp_hdr); 13708 proto = 0x11; 13709 break; 13710 case RTE_FLOW_ITEM_TYPE_TCP: 13711 size = sizeof(struct rte_tcp_hdr); 13712 proto = 0x06; 13713 break; 13714 case RTE_FLOW_ITEM_TYPE_VXLAN: 13715 size = sizeof(struct rte_vxlan_hdr); 13716 break; 13717 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 13718 size = sizeof(struct rte_vxlan_gpe_hdr); 13719 break; 13720 case RTE_FLOW_ITEM_TYPE_GRE: 13721 size = sizeof(struct rte_gre_hdr); 13722 proto = 0x2F; 13723 break; 13724 case RTE_FLOW_ITEM_TYPE_GRE_KEY: 13725 size = sizeof(rte_be32_t); 13726 proto = 0x0; 13727 break; 13728 case RTE_FLOW_ITEM_TYPE_MPLS: 13729 size = sizeof(struct rte_mpls_hdr); 13730 proto = 0x0; 13731 break; 13732 case RTE_FLOW_ITEM_TYPE_NVGRE: 13733 size = sizeof(struct rte_flow_item_nvgre); 13734 proto = 0x2F; 13735 break; 13736 case RTE_FLOW_ITEM_TYPE_GENEVE: 13737 size = sizeof(struct rte_geneve_hdr); 13738 break; 13739 case RTE_FLOW_ITEM_TYPE_GENEVE_OPT: 13740 opt = (const struct rte_flow_item_geneve_opt *) 13741 item->spec; 13742 size = offsetof(struct rte_flow_item_geneve_opt, 13743 option_len) + sizeof(uint8_t); 13744 if (opt->option_len && opt->data) { 13745 *total_size += opt->option_len * 13746 sizeof(uint32_t); 13747 rte_memcpy(data_tail - (*total_size), 13748 opt->data, 13749 opt->option_len * sizeof(uint32_t)); 13750 } 13751 break; 13752 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP: 13753 size = sizeof(rte_be32_t); 13754 proto = 0x73; 13755 break; 13756 case RTE_FLOW_ITEM_TYPE_ESP: 13757 size = sizeof(struct rte_esp_hdr); 13758 proto = 0x32; 13759 break; 13760 case RTE_FLOW_ITEM_TYPE_AH: 13761 size = sizeof(struct rte_flow_item_ah); 13762 proto = 0x33; 13763 break; 13764 case RTE_FLOW_ITEM_TYPE_GTP: 13765 if (gtp_psc < 0) { 13766 size = sizeof(struct rte_gtp_hdr); 13767 break; 13768 } 13769 if (gtp_psc != i + 1) { 13770 fprintf(stderr, 13771 "Error - GTP PSC does not follow GTP\n"); 13772 goto error; 13773 } 13774 gtp = item->spec; 13775 if (gtp->hdr.s == 1 || gtp->hdr.pn == 1) { 13776 /* Only E flag should be set. */ 13777 fprintf(stderr, 13778 "Error - GTP unsupported flags\n"); 13779 goto error; 13780 } else { 13781 struct rte_gtp_hdr_ext_word ext_word = { 13782 .next_ext = 0x85 13783 }; 13784 13785 /* We have to add GTP header extra word. */ 13786 *total_size += sizeof(ext_word); 13787 rte_memcpy(data_tail - (*total_size), 13788 &ext_word, sizeof(ext_word)); 13789 } 13790 size = sizeof(struct rte_gtp_hdr); 13791 break; 13792 case RTE_FLOW_ITEM_TYPE_GTP_PSC: 13793 if (gtp_psc >= 0) { 13794 fprintf(stderr, 13795 "Error - Multiple GTP PSC items\n"); 13796 goto error; 13797 } else { 13798 const struct rte_flow_item_gtp_psc 13799 *opt = item->spec; 13800 struct rte_gtp_psc_generic_hdr *hdr; 13801 size_t hdr_size = RTE_ALIGN(sizeof(*hdr), 13802 sizeof(int32_t)); 13803 13804 *total_size += hdr_size; 13805 hdr = (typeof(hdr))(data_tail - (*total_size)); 13806 memset(hdr, 0, hdr_size); 13807 *hdr = opt->hdr; 13808 hdr->ext_hdr_len = 1; 13809 gtp_psc = i; 13810 size = 0; 13811 } 13812 break; 13813 case RTE_FLOW_ITEM_TYPE_PFCP: 13814 size = sizeof(struct rte_flow_item_pfcp); 13815 break; 13816 case RTE_FLOW_ITEM_TYPE_FLEX: 13817 if (item->spec != NULL) { 13818 size = ((const struct rte_flow_item_flex *)item->spec)->length; 13819 src_spec = ((const struct rte_flow_item_flex *)item->spec)->pattern; 13820 } else { 13821 size = 0; 13822 src_spec = NULL; 13823 } 13824 break; 13825 case RTE_FLOW_ITEM_TYPE_GRE_OPTION: 13826 size = 0; 13827 if (item->spec) { 13828 const struct rte_flow_item_gre_opt 13829 *opt = item->spec; 13830 if (opt->checksum_rsvd.checksum) { 13831 *total_size += 13832 sizeof(opt->checksum_rsvd); 13833 rte_memcpy(data_tail - (*total_size), 13834 &opt->checksum_rsvd, 13835 sizeof(opt->checksum_rsvd)); 13836 } 13837 if (opt->key.key) { 13838 *total_size += sizeof(opt->key.key); 13839 rte_memcpy(data_tail - (*total_size), 13840 &opt->key.key, 13841 sizeof(opt->key.key)); 13842 } 13843 if (opt->sequence.sequence) { 13844 *total_size += sizeof(opt->sequence.sequence); 13845 rte_memcpy(data_tail - (*total_size), 13846 &opt->sequence.sequence, 13847 sizeof(opt->sequence.sequence)); 13848 } 13849 } 13850 proto = 0x2F; 13851 break; 13852 default: 13853 fprintf(stderr, "Error - Not supported item\n"); 13854 goto error; 13855 } 13856 if (size) { 13857 *total_size += size; 13858 rte_memcpy(data_tail - (*total_size), src_spec, size); 13859 /* update some fields which cannot be set by cmdline */ 13860 update_fields((data_tail - (*total_size)), item, 13861 upper_layer); 13862 upper_layer = proto; 13863 } 13864 } 13865 if (verbose_level & 0x1) 13866 printf("total data size is %zu\n", (*total_size)); 13867 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA); 13868 memmove(data, (data_tail - (*total_size)), *total_size); 13869 return; 13870 13871 error: 13872 *total_size = 0; 13873 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA); 13874 } 13875 13876 /** Populate help strings for current token (cmdline API). */ 13877 static int 13878 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, 13879 unsigned int size) 13880 { 13881 struct context *ctx = &cmd_flow_context; 13882 const struct token *token = &token_list[ctx->prev]; 13883 13884 (void)hdr; 13885 if (!size) 13886 return -1; 13887 /* Set token type and update global help with details. */ 13888 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN")); 13889 if (token->help) 13890 cmd_set_raw.help_str = token->help; 13891 else 13892 cmd_set_raw.help_str = token->name; 13893 return 0; 13894 } 13895 13896 /** Token definition template (cmdline API). */ 13897 static struct cmdline_token_hdr cmd_set_raw_token_hdr = { 13898 .ops = &(struct cmdline_token_ops){ 13899 .parse = cmd_flow_parse, 13900 .complete_get_nb = cmd_flow_complete_get_nb, 13901 .complete_get_elt = cmd_flow_complete_get_elt, 13902 .get_help = cmd_set_raw_get_help, 13903 }, 13904 .offset = 0, 13905 }; 13906 13907 /** Populate the next dynamic token. */ 13908 static void 13909 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr, 13910 cmdline_parse_token_hdr_t **hdr_inst) 13911 { 13912 struct context *ctx = &cmd_flow_context; 13913 13914 /* Always reinitialize context before requesting the first token. */ 13915 if (!(hdr_inst - cmd_set_raw.tokens)) { 13916 cmd_flow_context_init(ctx); 13917 ctx->curr = START_SET; 13918 } 13919 /* Return NULL when no more tokens are expected. */ 13920 if (!ctx->next_num && (ctx->curr != START_SET)) { 13921 *hdr = NULL; 13922 return; 13923 } 13924 /* Determine if command should end here. */ 13925 if (ctx->eol && ctx->last && ctx->next_num) { 13926 const enum index *list = ctx->next[ctx->next_num - 1]; 13927 int i; 13928 13929 for (i = 0; list[i]; ++i) { 13930 if (list[i] != END) 13931 continue; 13932 *hdr = NULL; 13933 return; 13934 } 13935 } 13936 *hdr = &cmd_set_raw_token_hdr; 13937 } 13938 13939 /** Token generator and output processing callback (cmdline API). */ 13940 static void 13941 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2) 13942 { 13943 if (cl == NULL) 13944 cmd_set_raw_tok(arg0, arg2); 13945 else 13946 cmd_set_raw_parsed(arg0); 13947 } 13948 13949 /** Global parser instance (cmdline API). */ 13950 cmdline_parse_inst_t cmd_set_raw = { 13951 .f = cmd_set_raw_cb, 13952 .data = NULL, /**< Unused. */ 13953 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */ 13954 .tokens = { 13955 NULL, 13956 }, /**< Tokens are returned by cmd_flow_tok(). */ 13957 }; 13958 13959 /* *** display raw_encap/raw_decap buf */ 13960 struct cmd_show_set_raw_result { 13961 cmdline_fixed_string_t cmd_show; 13962 cmdline_fixed_string_t cmd_what; 13963 cmdline_fixed_string_t cmd_all; 13964 uint16_t cmd_index; 13965 }; 13966 13967 static void 13968 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data) 13969 { 13970 struct cmd_show_set_raw_result *res = parsed_result; 13971 uint16_t index = res->cmd_index; 13972 uint8_t all = 0; 13973 uint8_t *raw_data = NULL; 13974 size_t raw_size = 0; 13975 char title[16] = {0}; 13976 13977 RTE_SET_USED(cl); 13978 RTE_SET_USED(data); 13979 if (!strcmp(res->cmd_all, "all")) { 13980 all = 1; 13981 index = 0; 13982 } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) { 13983 fprintf(stderr, "index should be 0-%u\n", 13984 RAW_ENCAP_CONFS_MAX_NUM - 1); 13985 return; 13986 } 13987 do { 13988 if (!strcmp(res->cmd_what, "raw_encap")) { 13989 raw_data = (uint8_t *)&raw_encap_confs[index].data; 13990 raw_size = raw_encap_confs[index].size; 13991 snprintf(title, 16, "\nindex: %u", index); 13992 rte_hexdump(stdout, title, raw_data, raw_size); 13993 } else { 13994 raw_data = (uint8_t *)&raw_decap_confs[index].data; 13995 raw_size = raw_decap_confs[index].size; 13996 snprintf(title, 16, "\nindex: %u", index); 13997 rte_hexdump(stdout, title, raw_data, raw_size); 13998 } 13999 } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM); 14000 } 14001 14002 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_show = 14003 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, 14004 cmd_show, "show"); 14005 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_what = 14006 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, 14007 cmd_what, "raw_encap#raw_decap"); 14008 static cmdline_parse_token_num_t cmd_show_set_raw_cmd_index = 14009 TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result, 14010 cmd_index, RTE_UINT16); 14011 static cmdline_parse_token_string_t cmd_show_set_raw_cmd_all = 14012 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, 14013 cmd_all, "all"); 14014 cmdline_parse_inst_t cmd_show_set_raw = { 14015 .f = cmd_show_set_raw_parsed, 14016 .data = NULL, 14017 .help_str = "show <raw_encap|raw_decap> <index>", 14018 .tokens = { 14019 (void *)&cmd_show_set_raw_cmd_show, 14020 (void *)&cmd_show_set_raw_cmd_what, 14021 (void *)&cmd_show_set_raw_cmd_index, 14022 NULL, 14023 }, 14024 }; 14025 cmdline_parse_inst_t cmd_show_set_raw_all = { 14026 .f = cmd_show_set_raw_parsed, 14027 .data = NULL, 14028 .help_str = "show <raw_encap|raw_decap> all", 14029 .tokens = { 14030 (void *)&cmd_show_set_raw_cmd_show, 14031 (void *)&cmd_show_set_raw_cmd_what, 14032 (void *)&cmd_show_set_raw_cmd_all, 14033 NULL, 14034 }, 14035 }; 14036