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