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