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