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