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