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