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