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