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