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