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