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