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