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