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