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