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