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