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