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