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