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