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