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