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