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