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