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