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