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