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