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