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