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