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