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