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