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