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 = sizeof(action_rss_data->key), 4854 .queue_num = RTE_MIN(nb_rxq, ACTION_RSS_QUEUE_NUM), 4855 .key = action_rss_data->key, 4856 .queue = action_rss_data->queue, 4857 }, 4858 .key = "testpmd's default RSS hash key, " 4859 "override it for better balancing", 4860 .queue = { 0 }, 4861 }; 4862 for (i = 0; i < action_rss_data->conf.queue_num; ++i) 4863 action_rss_data->queue[i] = i; 4864 if (!port_id_is_invalid(ctx->port, DISABLED_WARN) && 4865 ctx->port != (portid_t)RTE_PORT_ALL) { 4866 struct rte_eth_dev_info info; 4867 int ret2; 4868 4869 ret2 = rte_eth_dev_info_get(ctx->port, &info); 4870 if (ret2 != 0) 4871 return ret2; 4872 4873 action_rss_data->conf.key_len = 4874 RTE_MIN(sizeof(action_rss_data->key), 4875 info.hash_key_size); 4876 } 4877 action->conf = &action_rss_data->conf; 4878 return ret; 4879 } 4880 4881 /** 4882 * Parse func field for RSS action. 4883 * 4884 * The RTE_ETH_HASH_FUNCTION_* value to assign is derived from the 4885 * ACTION_RSS_FUNC_* index that called this function. 4886 */ 4887 static int 4888 parse_vc_action_rss_func(struct context *ctx, const struct token *token, 4889 const char *str, unsigned int len, 4890 void *buf, unsigned int size) 4891 { 4892 struct action_rss_data *action_rss_data; 4893 enum rte_eth_hash_function func; 4894 4895 (void)buf; 4896 (void)size; 4897 /* Token name must match. */ 4898 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 4899 return -1; 4900 switch (ctx->curr) { 4901 case ACTION_RSS_FUNC_DEFAULT: 4902 func = RTE_ETH_HASH_FUNCTION_DEFAULT; 4903 break; 4904 case ACTION_RSS_FUNC_TOEPLITZ: 4905 func = RTE_ETH_HASH_FUNCTION_TOEPLITZ; 4906 break; 4907 case ACTION_RSS_FUNC_SIMPLE_XOR: 4908 func = RTE_ETH_HASH_FUNCTION_SIMPLE_XOR; 4909 break; 4910 case ACTION_RSS_FUNC_SYMMETRIC_TOEPLITZ: 4911 func = RTE_ETH_HASH_FUNCTION_SYMMETRIC_TOEPLITZ; 4912 break; 4913 default: 4914 return -1; 4915 } 4916 if (!ctx->object) 4917 return len; 4918 action_rss_data = ctx->object; 4919 action_rss_data->conf.func = func; 4920 return len; 4921 } 4922 4923 /** 4924 * Parse type field for RSS action. 4925 * 4926 * Valid tokens are type field names and the "end" token. 4927 */ 4928 static int 4929 parse_vc_action_rss_type(struct context *ctx, const struct token *token, 4930 const char *str, unsigned int len, 4931 void *buf, unsigned int size) 4932 { 4933 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE); 4934 struct action_rss_data *action_rss_data; 4935 unsigned int i; 4936 4937 (void)token; 4938 (void)buf; 4939 (void)size; 4940 if (ctx->curr != ACTION_RSS_TYPE) 4941 return -1; 4942 if (!(ctx->objdata >> 16) && ctx->object) { 4943 action_rss_data = ctx->object; 4944 action_rss_data->conf.types = 0; 4945 } 4946 if (!strcmp_partial("end", str, len)) { 4947 ctx->objdata &= 0xffff; 4948 return len; 4949 } 4950 for (i = 0; rss_type_table[i].str; ++i) 4951 if (!strcmp_partial(rss_type_table[i].str, str, len)) 4952 break; 4953 if (!rss_type_table[i].str) 4954 return -1; 4955 ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff); 4956 /* Repeat token. */ 4957 if (ctx->next_num == RTE_DIM(ctx->next)) 4958 return -1; 4959 ctx->next[ctx->next_num++] = next; 4960 if (!ctx->object) 4961 return len; 4962 action_rss_data = ctx->object; 4963 action_rss_data->conf.types |= rss_type_table[i].rss_type; 4964 return len; 4965 } 4966 4967 /** 4968 * Parse queue field for RSS action. 4969 * 4970 * Valid tokens are queue indices and the "end" token. 4971 */ 4972 static int 4973 parse_vc_action_rss_queue(struct context *ctx, const struct token *token, 4974 const char *str, unsigned int len, 4975 void *buf, unsigned int size) 4976 { 4977 static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE); 4978 struct action_rss_data *action_rss_data; 4979 const struct arg *arg; 4980 int ret; 4981 int i; 4982 4983 (void)token; 4984 (void)buf; 4985 (void)size; 4986 if (ctx->curr != ACTION_RSS_QUEUE) 4987 return -1; 4988 i = ctx->objdata >> 16; 4989 if (!strcmp_partial("end", str, len)) { 4990 ctx->objdata &= 0xffff; 4991 goto end; 4992 } 4993 if (i >= ACTION_RSS_QUEUE_NUM) 4994 return -1; 4995 arg = ARGS_ENTRY_ARB(offsetof(struct action_rss_data, queue) + 4996 i * sizeof(action_rss_data->queue[i]), 4997 sizeof(action_rss_data->queue[i])); 4998 if (push_args(ctx, arg)) 4999 return -1; 5000 ret = parse_int(ctx, token, str, len, NULL, 0); 5001 if (ret < 0) { 5002 pop_args(ctx); 5003 return -1; 5004 } 5005 ++i; 5006 ctx->objdata = i << 16 | (ctx->objdata & 0xffff); 5007 /* Repeat token. */ 5008 if (ctx->next_num == RTE_DIM(ctx->next)) 5009 return -1; 5010 ctx->next[ctx->next_num++] = next; 5011 end: 5012 if (!ctx->object) 5013 return len; 5014 action_rss_data = ctx->object; 5015 action_rss_data->conf.queue_num = i; 5016 action_rss_data->conf.queue = i ? action_rss_data->queue : NULL; 5017 return len; 5018 } 5019 5020 /** Parse VXLAN encap action. */ 5021 static int 5022 parse_vc_action_vxlan_encap(struct context *ctx, const struct token *token, 5023 const char *str, unsigned int len, 5024 void *buf, unsigned int size) 5025 { 5026 struct buffer *out = buf; 5027 struct rte_flow_action *action; 5028 struct action_vxlan_encap_data *action_vxlan_encap_data; 5029 int ret; 5030 5031 ret = parse_vc(ctx, token, str, len, buf, size); 5032 if (ret < 0) 5033 return ret; 5034 /* Nothing else to do if there is no buffer. */ 5035 if (!out) 5036 return ret; 5037 if (!out->args.vc.actions_n) 5038 return -1; 5039 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 5040 /* Point to selected object. */ 5041 ctx->object = out->args.vc.data; 5042 ctx->objmask = NULL; 5043 /* Set up default configuration. */ 5044 action_vxlan_encap_data = ctx->object; 5045 *action_vxlan_encap_data = (struct action_vxlan_encap_data){ 5046 .conf = (struct rte_flow_action_vxlan_encap){ 5047 .definition = action_vxlan_encap_data->items, 5048 }, 5049 .items = { 5050 { 5051 .type = RTE_FLOW_ITEM_TYPE_ETH, 5052 .spec = &action_vxlan_encap_data->item_eth, 5053 .mask = &rte_flow_item_eth_mask, 5054 }, 5055 { 5056 .type = RTE_FLOW_ITEM_TYPE_VLAN, 5057 .spec = &action_vxlan_encap_data->item_vlan, 5058 .mask = &rte_flow_item_vlan_mask, 5059 }, 5060 { 5061 .type = RTE_FLOW_ITEM_TYPE_IPV4, 5062 .spec = &action_vxlan_encap_data->item_ipv4, 5063 .mask = &rte_flow_item_ipv4_mask, 5064 }, 5065 { 5066 .type = RTE_FLOW_ITEM_TYPE_UDP, 5067 .spec = &action_vxlan_encap_data->item_udp, 5068 .mask = &rte_flow_item_udp_mask, 5069 }, 5070 { 5071 .type = RTE_FLOW_ITEM_TYPE_VXLAN, 5072 .spec = &action_vxlan_encap_data->item_vxlan, 5073 .mask = &rte_flow_item_vxlan_mask, 5074 }, 5075 { 5076 .type = RTE_FLOW_ITEM_TYPE_END, 5077 }, 5078 }, 5079 .item_eth.type = 0, 5080 .item_vlan = { 5081 .tci = vxlan_encap_conf.vlan_tci, 5082 .inner_type = 0, 5083 }, 5084 .item_ipv4.hdr = { 5085 .src_addr = vxlan_encap_conf.ipv4_src, 5086 .dst_addr = vxlan_encap_conf.ipv4_dst, 5087 }, 5088 .item_udp.hdr = { 5089 .src_port = vxlan_encap_conf.udp_src, 5090 .dst_port = vxlan_encap_conf.udp_dst, 5091 }, 5092 .item_vxlan.flags = 0, 5093 }; 5094 memcpy(action_vxlan_encap_data->item_eth.dst.addr_bytes, 5095 vxlan_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 5096 memcpy(action_vxlan_encap_data->item_eth.src.addr_bytes, 5097 vxlan_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 5098 if (!vxlan_encap_conf.select_ipv4) { 5099 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.src_addr, 5100 &vxlan_encap_conf.ipv6_src, 5101 sizeof(vxlan_encap_conf.ipv6_src)); 5102 memcpy(&action_vxlan_encap_data->item_ipv6.hdr.dst_addr, 5103 &vxlan_encap_conf.ipv6_dst, 5104 sizeof(vxlan_encap_conf.ipv6_dst)); 5105 action_vxlan_encap_data->items[2] = (struct rte_flow_item){ 5106 .type = RTE_FLOW_ITEM_TYPE_IPV6, 5107 .spec = &action_vxlan_encap_data->item_ipv6, 5108 .mask = &rte_flow_item_ipv6_mask, 5109 }; 5110 } 5111 if (!vxlan_encap_conf.select_vlan) 5112 action_vxlan_encap_data->items[1].type = 5113 RTE_FLOW_ITEM_TYPE_VOID; 5114 if (vxlan_encap_conf.select_tos_ttl) { 5115 if (vxlan_encap_conf.select_ipv4) { 5116 static struct rte_flow_item_ipv4 ipv4_mask_tos; 5117 5118 memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask, 5119 sizeof(ipv4_mask_tos)); 5120 ipv4_mask_tos.hdr.type_of_service = 0xff; 5121 ipv4_mask_tos.hdr.time_to_live = 0xff; 5122 action_vxlan_encap_data->item_ipv4.hdr.type_of_service = 5123 vxlan_encap_conf.ip_tos; 5124 action_vxlan_encap_data->item_ipv4.hdr.time_to_live = 5125 vxlan_encap_conf.ip_ttl; 5126 action_vxlan_encap_data->items[2].mask = 5127 &ipv4_mask_tos; 5128 } else { 5129 static struct rte_flow_item_ipv6 ipv6_mask_tos; 5130 5131 memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask, 5132 sizeof(ipv6_mask_tos)); 5133 ipv6_mask_tos.hdr.vtc_flow |= 5134 RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT); 5135 ipv6_mask_tos.hdr.hop_limits = 0xff; 5136 action_vxlan_encap_data->item_ipv6.hdr.vtc_flow |= 5137 rte_cpu_to_be_32 5138 ((uint32_t)vxlan_encap_conf.ip_tos << 5139 RTE_IPV6_HDR_TC_SHIFT); 5140 action_vxlan_encap_data->item_ipv6.hdr.hop_limits = 5141 vxlan_encap_conf.ip_ttl; 5142 action_vxlan_encap_data->items[2].mask = 5143 &ipv6_mask_tos; 5144 } 5145 } 5146 memcpy(action_vxlan_encap_data->item_vxlan.vni, vxlan_encap_conf.vni, 5147 RTE_DIM(vxlan_encap_conf.vni)); 5148 action->conf = &action_vxlan_encap_data->conf; 5149 return ret; 5150 } 5151 5152 /** Parse NVGRE encap action. */ 5153 static int 5154 parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token, 5155 const char *str, unsigned int len, 5156 void *buf, unsigned int size) 5157 { 5158 struct buffer *out = buf; 5159 struct rte_flow_action *action; 5160 struct action_nvgre_encap_data *action_nvgre_encap_data; 5161 int ret; 5162 5163 ret = parse_vc(ctx, token, str, len, buf, size); 5164 if (ret < 0) 5165 return ret; 5166 /* Nothing else to do if there is no buffer. */ 5167 if (!out) 5168 return ret; 5169 if (!out->args.vc.actions_n) 5170 return -1; 5171 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 5172 /* Point to selected object. */ 5173 ctx->object = out->args.vc.data; 5174 ctx->objmask = NULL; 5175 /* Set up default configuration. */ 5176 action_nvgre_encap_data = ctx->object; 5177 *action_nvgre_encap_data = (struct action_nvgre_encap_data){ 5178 .conf = (struct rte_flow_action_nvgre_encap){ 5179 .definition = action_nvgre_encap_data->items, 5180 }, 5181 .items = { 5182 { 5183 .type = RTE_FLOW_ITEM_TYPE_ETH, 5184 .spec = &action_nvgre_encap_data->item_eth, 5185 .mask = &rte_flow_item_eth_mask, 5186 }, 5187 { 5188 .type = RTE_FLOW_ITEM_TYPE_VLAN, 5189 .spec = &action_nvgre_encap_data->item_vlan, 5190 .mask = &rte_flow_item_vlan_mask, 5191 }, 5192 { 5193 .type = RTE_FLOW_ITEM_TYPE_IPV4, 5194 .spec = &action_nvgre_encap_data->item_ipv4, 5195 .mask = &rte_flow_item_ipv4_mask, 5196 }, 5197 { 5198 .type = RTE_FLOW_ITEM_TYPE_NVGRE, 5199 .spec = &action_nvgre_encap_data->item_nvgre, 5200 .mask = &rte_flow_item_nvgre_mask, 5201 }, 5202 { 5203 .type = RTE_FLOW_ITEM_TYPE_END, 5204 }, 5205 }, 5206 .item_eth.type = 0, 5207 .item_vlan = { 5208 .tci = nvgre_encap_conf.vlan_tci, 5209 .inner_type = 0, 5210 }, 5211 .item_ipv4.hdr = { 5212 .src_addr = nvgre_encap_conf.ipv4_src, 5213 .dst_addr = nvgre_encap_conf.ipv4_dst, 5214 }, 5215 .item_nvgre.flow_id = 0, 5216 }; 5217 memcpy(action_nvgre_encap_data->item_eth.dst.addr_bytes, 5218 nvgre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 5219 memcpy(action_nvgre_encap_data->item_eth.src.addr_bytes, 5220 nvgre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 5221 if (!nvgre_encap_conf.select_ipv4) { 5222 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.src_addr, 5223 &nvgre_encap_conf.ipv6_src, 5224 sizeof(nvgre_encap_conf.ipv6_src)); 5225 memcpy(&action_nvgre_encap_data->item_ipv6.hdr.dst_addr, 5226 &nvgre_encap_conf.ipv6_dst, 5227 sizeof(nvgre_encap_conf.ipv6_dst)); 5228 action_nvgre_encap_data->items[2] = (struct rte_flow_item){ 5229 .type = RTE_FLOW_ITEM_TYPE_IPV6, 5230 .spec = &action_nvgre_encap_data->item_ipv6, 5231 .mask = &rte_flow_item_ipv6_mask, 5232 }; 5233 } 5234 if (!nvgre_encap_conf.select_vlan) 5235 action_nvgre_encap_data->items[1].type = 5236 RTE_FLOW_ITEM_TYPE_VOID; 5237 memcpy(action_nvgre_encap_data->item_nvgre.tni, nvgre_encap_conf.tni, 5238 RTE_DIM(nvgre_encap_conf.tni)); 5239 action->conf = &action_nvgre_encap_data->conf; 5240 return ret; 5241 } 5242 5243 /** Parse l2 encap action. */ 5244 static int 5245 parse_vc_action_l2_encap(struct context *ctx, const struct token *token, 5246 const char *str, unsigned int len, 5247 void *buf, unsigned int size) 5248 { 5249 struct buffer *out = buf; 5250 struct rte_flow_action *action; 5251 struct action_raw_encap_data *action_encap_data; 5252 struct rte_flow_item_eth eth = { .type = 0, }; 5253 struct rte_flow_item_vlan vlan = { 5254 .tci = mplsoudp_encap_conf.vlan_tci, 5255 .inner_type = 0, 5256 }; 5257 uint8_t *header; 5258 int ret; 5259 5260 ret = parse_vc(ctx, token, str, len, buf, size); 5261 if (ret < 0) 5262 return ret; 5263 /* Nothing else to do if there is no buffer. */ 5264 if (!out) 5265 return ret; 5266 if (!out->args.vc.actions_n) 5267 return -1; 5268 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 5269 /* Point to selected object. */ 5270 ctx->object = out->args.vc.data; 5271 ctx->objmask = NULL; 5272 /* Copy the headers to the buffer. */ 5273 action_encap_data = ctx->object; 5274 *action_encap_data = (struct action_raw_encap_data) { 5275 .conf = (struct rte_flow_action_raw_encap){ 5276 .data = action_encap_data->data, 5277 }, 5278 .data = {}, 5279 }; 5280 header = action_encap_data->data; 5281 if (l2_encap_conf.select_vlan) 5282 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 5283 else if (l2_encap_conf.select_ipv4) 5284 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 5285 else 5286 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 5287 memcpy(eth.dst.addr_bytes, 5288 l2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 5289 memcpy(eth.src.addr_bytes, 5290 l2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 5291 memcpy(header, ð, sizeof(eth)); 5292 header += sizeof(eth); 5293 if (l2_encap_conf.select_vlan) { 5294 if (l2_encap_conf.select_ipv4) 5295 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 5296 else 5297 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 5298 memcpy(header, &vlan, sizeof(vlan)); 5299 header += sizeof(vlan); 5300 } 5301 action_encap_data->conf.size = header - 5302 action_encap_data->data; 5303 action->conf = &action_encap_data->conf; 5304 return ret; 5305 } 5306 5307 /** Parse l2 decap action. */ 5308 static int 5309 parse_vc_action_l2_decap(struct context *ctx, const struct token *token, 5310 const char *str, unsigned int len, 5311 void *buf, unsigned int size) 5312 { 5313 struct buffer *out = buf; 5314 struct rte_flow_action *action; 5315 struct action_raw_decap_data *action_decap_data; 5316 struct rte_flow_item_eth eth = { .type = 0, }; 5317 struct rte_flow_item_vlan vlan = { 5318 .tci = mplsoudp_encap_conf.vlan_tci, 5319 .inner_type = 0, 5320 }; 5321 uint8_t *header; 5322 int ret; 5323 5324 ret = parse_vc(ctx, token, str, len, buf, size); 5325 if (ret < 0) 5326 return ret; 5327 /* Nothing else to do if there is no buffer. */ 5328 if (!out) 5329 return ret; 5330 if (!out->args.vc.actions_n) 5331 return -1; 5332 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 5333 /* Point to selected object. */ 5334 ctx->object = out->args.vc.data; 5335 ctx->objmask = NULL; 5336 /* Copy the headers to the buffer. */ 5337 action_decap_data = ctx->object; 5338 *action_decap_data = (struct action_raw_decap_data) { 5339 .conf = (struct rte_flow_action_raw_decap){ 5340 .data = action_decap_data->data, 5341 }, 5342 .data = {}, 5343 }; 5344 header = action_decap_data->data; 5345 if (l2_decap_conf.select_vlan) 5346 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 5347 memcpy(header, ð, sizeof(eth)); 5348 header += sizeof(eth); 5349 if (l2_decap_conf.select_vlan) { 5350 memcpy(header, &vlan, sizeof(vlan)); 5351 header += sizeof(vlan); 5352 } 5353 action_decap_data->conf.size = header - 5354 action_decap_data->data; 5355 action->conf = &action_decap_data->conf; 5356 return ret; 5357 } 5358 5359 #define ETHER_TYPE_MPLS_UNICAST 0x8847 5360 5361 /** Parse MPLSOGRE encap action. */ 5362 static int 5363 parse_vc_action_mplsogre_encap(struct context *ctx, const struct token *token, 5364 const char *str, unsigned int len, 5365 void *buf, unsigned int size) 5366 { 5367 struct buffer *out = buf; 5368 struct rte_flow_action *action; 5369 struct action_raw_encap_data *action_encap_data; 5370 struct rte_flow_item_eth eth = { .type = 0, }; 5371 struct rte_flow_item_vlan vlan = { 5372 .tci = mplsogre_encap_conf.vlan_tci, 5373 .inner_type = 0, 5374 }; 5375 struct rte_flow_item_ipv4 ipv4 = { 5376 .hdr = { 5377 .src_addr = mplsogre_encap_conf.ipv4_src, 5378 .dst_addr = mplsogre_encap_conf.ipv4_dst, 5379 .next_proto_id = IPPROTO_GRE, 5380 .version_ihl = RTE_IPV4_VHL_DEF, 5381 .time_to_live = IPDEFTTL, 5382 }, 5383 }; 5384 struct rte_flow_item_ipv6 ipv6 = { 5385 .hdr = { 5386 .proto = IPPROTO_GRE, 5387 .hop_limits = IPDEFTTL, 5388 }, 5389 }; 5390 struct rte_flow_item_gre gre = { 5391 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST), 5392 }; 5393 struct rte_flow_item_mpls mpls = { 5394 .ttl = 0, 5395 }; 5396 uint8_t *header; 5397 int ret; 5398 5399 ret = parse_vc(ctx, token, str, len, buf, size); 5400 if (ret < 0) 5401 return ret; 5402 /* Nothing else to do if there is no buffer. */ 5403 if (!out) 5404 return ret; 5405 if (!out->args.vc.actions_n) 5406 return -1; 5407 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 5408 /* Point to selected object. */ 5409 ctx->object = out->args.vc.data; 5410 ctx->objmask = NULL; 5411 /* Copy the headers to the buffer. */ 5412 action_encap_data = ctx->object; 5413 *action_encap_data = (struct action_raw_encap_data) { 5414 .conf = (struct rte_flow_action_raw_encap){ 5415 .data = action_encap_data->data, 5416 }, 5417 .data = {}, 5418 .preserve = {}, 5419 }; 5420 header = action_encap_data->data; 5421 if (mplsogre_encap_conf.select_vlan) 5422 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 5423 else if (mplsogre_encap_conf.select_ipv4) 5424 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 5425 else 5426 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 5427 memcpy(eth.dst.addr_bytes, 5428 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 5429 memcpy(eth.src.addr_bytes, 5430 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 5431 memcpy(header, ð, sizeof(eth)); 5432 header += sizeof(eth); 5433 if (mplsogre_encap_conf.select_vlan) { 5434 if (mplsogre_encap_conf.select_ipv4) 5435 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 5436 else 5437 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 5438 memcpy(header, &vlan, sizeof(vlan)); 5439 header += sizeof(vlan); 5440 } 5441 if (mplsogre_encap_conf.select_ipv4) { 5442 memcpy(header, &ipv4, sizeof(ipv4)); 5443 header += sizeof(ipv4); 5444 } else { 5445 memcpy(&ipv6.hdr.src_addr, 5446 &mplsogre_encap_conf.ipv6_src, 5447 sizeof(mplsogre_encap_conf.ipv6_src)); 5448 memcpy(&ipv6.hdr.dst_addr, 5449 &mplsogre_encap_conf.ipv6_dst, 5450 sizeof(mplsogre_encap_conf.ipv6_dst)); 5451 memcpy(header, &ipv6, sizeof(ipv6)); 5452 header += sizeof(ipv6); 5453 } 5454 memcpy(header, &gre, sizeof(gre)); 5455 header += sizeof(gre); 5456 memcpy(mpls.label_tc_s, mplsogre_encap_conf.label, 5457 RTE_DIM(mplsogre_encap_conf.label)); 5458 mpls.label_tc_s[2] |= 0x1; 5459 memcpy(header, &mpls, sizeof(mpls)); 5460 header += sizeof(mpls); 5461 action_encap_data->conf.size = header - 5462 action_encap_data->data; 5463 action->conf = &action_encap_data->conf; 5464 return ret; 5465 } 5466 5467 /** Parse MPLSOGRE decap action. */ 5468 static int 5469 parse_vc_action_mplsogre_decap(struct context *ctx, const struct token *token, 5470 const char *str, unsigned int len, 5471 void *buf, unsigned int size) 5472 { 5473 struct buffer *out = buf; 5474 struct rte_flow_action *action; 5475 struct action_raw_decap_data *action_decap_data; 5476 struct rte_flow_item_eth eth = { .type = 0, }; 5477 struct rte_flow_item_vlan vlan = {.tci = 0}; 5478 struct rte_flow_item_ipv4 ipv4 = { 5479 .hdr = { 5480 .next_proto_id = IPPROTO_GRE, 5481 }, 5482 }; 5483 struct rte_flow_item_ipv6 ipv6 = { 5484 .hdr = { 5485 .proto = IPPROTO_GRE, 5486 }, 5487 }; 5488 struct rte_flow_item_gre gre = { 5489 .protocol = rte_cpu_to_be_16(ETHER_TYPE_MPLS_UNICAST), 5490 }; 5491 struct rte_flow_item_mpls mpls; 5492 uint8_t *header; 5493 int ret; 5494 5495 ret = parse_vc(ctx, token, str, len, buf, size); 5496 if (ret < 0) 5497 return ret; 5498 /* Nothing else to do if there is no buffer. */ 5499 if (!out) 5500 return ret; 5501 if (!out->args.vc.actions_n) 5502 return -1; 5503 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 5504 /* Point to selected object. */ 5505 ctx->object = out->args.vc.data; 5506 ctx->objmask = NULL; 5507 /* Copy the headers to the buffer. */ 5508 action_decap_data = ctx->object; 5509 *action_decap_data = (struct action_raw_decap_data) { 5510 .conf = (struct rte_flow_action_raw_decap){ 5511 .data = action_decap_data->data, 5512 }, 5513 .data = {}, 5514 }; 5515 header = action_decap_data->data; 5516 if (mplsogre_decap_conf.select_vlan) 5517 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 5518 else if (mplsogre_encap_conf.select_ipv4) 5519 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 5520 else 5521 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 5522 memcpy(eth.dst.addr_bytes, 5523 mplsogre_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 5524 memcpy(eth.src.addr_bytes, 5525 mplsogre_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 5526 memcpy(header, ð, sizeof(eth)); 5527 header += sizeof(eth); 5528 if (mplsogre_encap_conf.select_vlan) { 5529 if (mplsogre_encap_conf.select_ipv4) 5530 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 5531 else 5532 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 5533 memcpy(header, &vlan, sizeof(vlan)); 5534 header += sizeof(vlan); 5535 } 5536 if (mplsogre_encap_conf.select_ipv4) { 5537 memcpy(header, &ipv4, sizeof(ipv4)); 5538 header += sizeof(ipv4); 5539 } else { 5540 memcpy(header, &ipv6, sizeof(ipv6)); 5541 header += sizeof(ipv6); 5542 } 5543 memcpy(header, &gre, sizeof(gre)); 5544 header += sizeof(gre); 5545 memset(&mpls, 0, sizeof(mpls)); 5546 memcpy(header, &mpls, sizeof(mpls)); 5547 header += sizeof(mpls); 5548 action_decap_data->conf.size = header - 5549 action_decap_data->data; 5550 action->conf = &action_decap_data->conf; 5551 return ret; 5552 } 5553 5554 /** Parse MPLSOUDP encap action. */ 5555 static int 5556 parse_vc_action_mplsoudp_encap(struct context *ctx, const struct token *token, 5557 const char *str, unsigned int len, 5558 void *buf, unsigned int size) 5559 { 5560 struct buffer *out = buf; 5561 struct rte_flow_action *action; 5562 struct action_raw_encap_data *action_encap_data; 5563 struct rte_flow_item_eth eth = { .type = 0, }; 5564 struct rte_flow_item_vlan vlan = { 5565 .tci = mplsoudp_encap_conf.vlan_tci, 5566 .inner_type = 0, 5567 }; 5568 struct rte_flow_item_ipv4 ipv4 = { 5569 .hdr = { 5570 .src_addr = mplsoudp_encap_conf.ipv4_src, 5571 .dst_addr = mplsoudp_encap_conf.ipv4_dst, 5572 .next_proto_id = IPPROTO_UDP, 5573 .version_ihl = RTE_IPV4_VHL_DEF, 5574 .time_to_live = IPDEFTTL, 5575 }, 5576 }; 5577 struct rte_flow_item_ipv6 ipv6 = { 5578 .hdr = { 5579 .proto = IPPROTO_UDP, 5580 .hop_limits = IPDEFTTL, 5581 }, 5582 }; 5583 struct rte_flow_item_udp udp = { 5584 .hdr = { 5585 .src_port = mplsoudp_encap_conf.udp_src, 5586 .dst_port = mplsoudp_encap_conf.udp_dst, 5587 }, 5588 }; 5589 struct rte_flow_item_mpls mpls; 5590 uint8_t *header; 5591 int ret; 5592 5593 ret = parse_vc(ctx, token, str, len, buf, size); 5594 if (ret < 0) 5595 return ret; 5596 /* Nothing else to do if there is no buffer. */ 5597 if (!out) 5598 return ret; 5599 if (!out->args.vc.actions_n) 5600 return -1; 5601 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 5602 /* Point to selected object. */ 5603 ctx->object = out->args.vc.data; 5604 ctx->objmask = NULL; 5605 /* Copy the headers to the buffer. */ 5606 action_encap_data = ctx->object; 5607 *action_encap_data = (struct action_raw_encap_data) { 5608 .conf = (struct rte_flow_action_raw_encap){ 5609 .data = action_encap_data->data, 5610 }, 5611 .data = {}, 5612 .preserve = {}, 5613 }; 5614 header = action_encap_data->data; 5615 if (mplsoudp_encap_conf.select_vlan) 5616 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 5617 else if (mplsoudp_encap_conf.select_ipv4) 5618 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 5619 else 5620 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 5621 memcpy(eth.dst.addr_bytes, 5622 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 5623 memcpy(eth.src.addr_bytes, 5624 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 5625 memcpy(header, ð, sizeof(eth)); 5626 header += sizeof(eth); 5627 if (mplsoudp_encap_conf.select_vlan) { 5628 if (mplsoudp_encap_conf.select_ipv4) 5629 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 5630 else 5631 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 5632 memcpy(header, &vlan, sizeof(vlan)); 5633 header += sizeof(vlan); 5634 } 5635 if (mplsoudp_encap_conf.select_ipv4) { 5636 memcpy(header, &ipv4, sizeof(ipv4)); 5637 header += sizeof(ipv4); 5638 } else { 5639 memcpy(&ipv6.hdr.src_addr, 5640 &mplsoudp_encap_conf.ipv6_src, 5641 sizeof(mplsoudp_encap_conf.ipv6_src)); 5642 memcpy(&ipv6.hdr.dst_addr, 5643 &mplsoudp_encap_conf.ipv6_dst, 5644 sizeof(mplsoudp_encap_conf.ipv6_dst)); 5645 memcpy(header, &ipv6, sizeof(ipv6)); 5646 header += sizeof(ipv6); 5647 } 5648 memcpy(header, &udp, sizeof(udp)); 5649 header += sizeof(udp); 5650 memcpy(mpls.label_tc_s, mplsoudp_encap_conf.label, 5651 RTE_DIM(mplsoudp_encap_conf.label)); 5652 mpls.label_tc_s[2] |= 0x1; 5653 memcpy(header, &mpls, sizeof(mpls)); 5654 header += sizeof(mpls); 5655 action_encap_data->conf.size = header - 5656 action_encap_data->data; 5657 action->conf = &action_encap_data->conf; 5658 return ret; 5659 } 5660 5661 /** Parse MPLSOUDP decap action. */ 5662 static int 5663 parse_vc_action_mplsoudp_decap(struct context *ctx, const struct token *token, 5664 const char *str, unsigned int len, 5665 void *buf, unsigned int size) 5666 { 5667 struct buffer *out = buf; 5668 struct rte_flow_action *action; 5669 struct action_raw_decap_data *action_decap_data; 5670 struct rte_flow_item_eth eth = { .type = 0, }; 5671 struct rte_flow_item_vlan vlan = {.tci = 0}; 5672 struct rte_flow_item_ipv4 ipv4 = { 5673 .hdr = { 5674 .next_proto_id = IPPROTO_UDP, 5675 }, 5676 }; 5677 struct rte_flow_item_ipv6 ipv6 = { 5678 .hdr = { 5679 .proto = IPPROTO_UDP, 5680 }, 5681 }; 5682 struct rte_flow_item_udp udp = { 5683 .hdr = { 5684 .dst_port = rte_cpu_to_be_16(6635), 5685 }, 5686 }; 5687 struct rte_flow_item_mpls mpls; 5688 uint8_t *header; 5689 int ret; 5690 5691 ret = parse_vc(ctx, token, str, len, buf, size); 5692 if (ret < 0) 5693 return ret; 5694 /* Nothing else to do if there is no buffer. */ 5695 if (!out) 5696 return ret; 5697 if (!out->args.vc.actions_n) 5698 return -1; 5699 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 5700 /* Point to selected object. */ 5701 ctx->object = out->args.vc.data; 5702 ctx->objmask = NULL; 5703 /* Copy the headers to the buffer. */ 5704 action_decap_data = ctx->object; 5705 *action_decap_data = (struct action_raw_decap_data) { 5706 .conf = (struct rte_flow_action_raw_decap){ 5707 .data = action_decap_data->data, 5708 }, 5709 .data = {}, 5710 }; 5711 header = action_decap_data->data; 5712 if (mplsoudp_decap_conf.select_vlan) 5713 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN); 5714 else if (mplsoudp_encap_conf.select_ipv4) 5715 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 5716 else 5717 eth.type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 5718 memcpy(eth.dst.addr_bytes, 5719 mplsoudp_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); 5720 memcpy(eth.src.addr_bytes, 5721 mplsoudp_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); 5722 memcpy(header, ð, sizeof(eth)); 5723 header += sizeof(eth); 5724 if (mplsoudp_encap_conf.select_vlan) { 5725 if (mplsoudp_encap_conf.select_ipv4) 5726 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); 5727 else 5728 vlan.inner_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); 5729 memcpy(header, &vlan, sizeof(vlan)); 5730 header += sizeof(vlan); 5731 } 5732 if (mplsoudp_encap_conf.select_ipv4) { 5733 memcpy(header, &ipv4, sizeof(ipv4)); 5734 header += sizeof(ipv4); 5735 } else { 5736 memcpy(header, &ipv6, sizeof(ipv6)); 5737 header += sizeof(ipv6); 5738 } 5739 memcpy(header, &udp, sizeof(udp)); 5740 header += sizeof(udp); 5741 memset(&mpls, 0, sizeof(mpls)); 5742 memcpy(header, &mpls, sizeof(mpls)); 5743 header += sizeof(mpls); 5744 action_decap_data->conf.size = header - 5745 action_decap_data->data; 5746 action->conf = &action_decap_data->conf; 5747 return ret; 5748 } 5749 5750 static int 5751 parse_vc_action_raw_decap_index(struct context *ctx, const struct token *token, 5752 const char *str, unsigned int len, void *buf, 5753 unsigned int size) 5754 { 5755 struct action_raw_decap_data *action_raw_decap_data; 5756 struct rte_flow_action *action; 5757 const struct arg *arg; 5758 struct buffer *out = buf; 5759 int ret; 5760 uint16_t idx; 5761 5762 RTE_SET_USED(token); 5763 RTE_SET_USED(buf); 5764 RTE_SET_USED(size); 5765 arg = ARGS_ENTRY_ARB_BOUNDED 5766 (offsetof(struct action_raw_decap_data, idx), 5767 sizeof(((struct action_raw_decap_data *)0)->idx), 5768 0, RAW_ENCAP_CONFS_MAX_NUM - 1); 5769 if (push_args(ctx, arg)) 5770 return -1; 5771 ret = parse_int(ctx, token, str, len, NULL, 0); 5772 if (ret < 0) { 5773 pop_args(ctx); 5774 return -1; 5775 } 5776 if (!ctx->object) 5777 return len; 5778 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 5779 action_raw_decap_data = ctx->object; 5780 idx = action_raw_decap_data->idx; 5781 action_raw_decap_data->conf.data = raw_decap_confs[idx].data; 5782 action_raw_decap_data->conf.size = raw_decap_confs[idx].size; 5783 action->conf = &action_raw_decap_data->conf; 5784 return len; 5785 } 5786 5787 5788 static int 5789 parse_vc_action_raw_encap_index(struct context *ctx, const struct token *token, 5790 const char *str, unsigned int len, void *buf, 5791 unsigned int size) 5792 { 5793 struct action_raw_encap_data *action_raw_encap_data; 5794 struct rte_flow_action *action; 5795 const struct arg *arg; 5796 struct buffer *out = buf; 5797 int ret; 5798 uint16_t idx; 5799 5800 RTE_SET_USED(token); 5801 RTE_SET_USED(buf); 5802 RTE_SET_USED(size); 5803 if (ctx->curr != ACTION_RAW_ENCAP_INDEX_VALUE) 5804 return -1; 5805 arg = ARGS_ENTRY_ARB_BOUNDED 5806 (offsetof(struct action_raw_encap_data, idx), 5807 sizeof(((struct action_raw_encap_data *)0)->idx), 5808 0, RAW_ENCAP_CONFS_MAX_NUM - 1); 5809 if (push_args(ctx, arg)) 5810 return -1; 5811 ret = parse_int(ctx, token, str, len, NULL, 0); 5812 if (ret < 0) { 5813 pop_args(ctx); 5814 return -1; 5815 } 5816 if (!ctx->object) 5817 return len; 5818 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 5819 action_raw_encap_data = ctx->object; 5820 idx = action_raw_encap_data->idx; 5821 action_raw_encap_data->conf.data = raw_encap_confs[idx].data; 5822 action_raw_encap_data->conf.size = raw_encap_confs[idx].size; 5823 action_raw_encap_data->conf.preserve = NULL; 5824 action->conf = &action_raw_encap_data->conf; 5825 return len; 5826 } 5827 5828 static int 5829 parse_vc_action_raw_encap(struct context *ctx, const struct token *token, 5830 const char *str, unsigned int len, void *buf, 5831 unsigned int size) 5832 { 5833 struct buffer *out = buf; 5834 struct rte_flow_action *action; 5835 struct action_raw_encap_data *action_raw_encap_data = NULL; 5836 int ret; 5837 5838 ret = parse_vc(ctx, token, str, len, buf, size); 5839 if (ret < 0) 5840 return ret; 5841 /* Nothing else to do if there is no buffer. */ 5842 if (!out) 5843 return ret; 5844 if (!out->args.vc.actions_n) 5845 return -1; 5846 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 5847 /* Point to selected object. */ 5848 ctx->object = out->args.vc.data; 5849 ctx->objmask = NULL; 5850 /* Copy the headers to the buffer. */ 5851 action_raw_encap_data = ctx->object; 5852 action_raw_encap_data->conf.data = raw_encap_confs[0].data; 5853 action_raw_encap_data->conf.preserve = NULL; 5854 action_raw_encap_data->conf.size = raw_encap_confs[0].size; 5855 action->conf = &action_raw_encap_data->conf; 5856 return ret; 5857 } 5858 5859 static int 5860 parse_vc_action_raw_decap(struct context *ctx, const struct token *token, 5861 const char *str, unsigned int len, void *buf, 5862 unsigned int size) 5863 { 5864 struct buffer *out = buf; 5865 struct rte_flow_action *action; 5866 struct action_raw_decap_data *action_raw_decap_data = NULL; 5867 int ret; 5868 5869 ret = parse_vc(ctx, token, str, len, buf, size); 5870 if (ret < 0) 5871 return ret; 5872 /* Nothing else to do if there is no buffer. */ 5873 if (!out) 5874 return ret; 5875 if (!out->args.vc.actions_n) 5876 return -1; 5877 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 5878 /* Point to selected object. */ 5879 ctx->object = out->args.vc.data; 5880 ctx->objmask = NULL; 5881 /* Copy the headers to the buffer. */ 5882 action_raw_decap_data = ctx->object; 5883 action_raw_decap_data->conf.data = raw_decap_confs[0].data; 5884 action_raw_decap_data->conf.size = raw_decap_confs[0].size; 5885 action->conf = &action_raw_decap_data->conf; 5886 return ret; 5887 } 5888 5889 static int 5890 parse_vc_action_set_meta(struct context *ctx, const struct token *token, 5891 const char *str, unsigned int len, void *buf, 5892 unsigned int size) 5893 { 5894 int ret; 5895 5896 ret = parse_vc(ctx, token, str, len, buf, size); 5897 if (ret < 0) 5898 return ret; 5899 ret = rte_flow_dynf_metadata_register(); 5900 if (ret < 0) 5901 return -1; 5902 return len; 5903 } 5904 5905 static int 5906 parse_vc_action_sample(struct context *ctx, const struct token *token, 5907 const char *str, unsigned int len, void *buf, 5908 unsigned int size) 5909 { 5910 struct buffer *out = buf; 5911 struct rte_flow_action *action; 5912 struct action_sample_data *action_sample_data = NULL; 5913 static struct rte_flow_action end_action = { 5914 RTE_FLOW_ACTION_TYPE_END, 0 5915 }; 5916 int ret; 5917 5918 ret = parse_vc(ctx, token, str, len, buf, size); 5919 if (ret < 0) 5920 return ret; 5921 /* Nothing else to do if there is no buffer. */ 5922 if (!out) 5923 return ret; 5924 if (!out->args.vc.actions_n) 5925 return -1; 5926 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 5927 /* Point to selected object. */ 5928 ctx->object = out->args.vc.data; 5929 ctx->objmask = NULL; 5930 /* Copy the headers to the buffer. */ 5931 action_sample_data = ctx->object; 5932 action_sample_data->conf.actions = &end_action; 5933 action->conf = &action_sample_data->conf; 5934 return ret; 5935 } 5936 5937 static int 5938 parse_vc_action_sample_index(struct context *ctx, const struct token *token, 5939 const char *str, unsigned int len, void *buf, 5940 unsigned int size) 5941 { 5942 struct action_sample_data *action_sample_data; 5943 struct rte_flow_action *action; 5944 const struct arg *arg; 5945 struct buffer *out = buf; 5946 int ret; 5947 uint16_t idx; 5948 5949 RTE_SET_USED(token); 5950 RTE_SET_USED(buf); 5951 RTE_SET_USED(size); 5952 if (ctx->curr != ACTION_SAMPLE_INDEX_VALUE) 5953 return -1; 5954 arg = ARGS_ENTRY_ARB_BOUNDED 5955 (offsetof(struct action_sample_data, idx), 5956 sizeof(((struct action_sample_data *)0)->idx), 5957 0, RAW_SAMPLE_CONFS_MAX_NUM - 1); 5958 if (push_args(ctx, arg)) 5959 return -1; 5960 ret = parse_int(ctx, token, str, len, NULL, 0); 5961 if (ret < 0) { 5962 pop_args(ctx); 5963 return -1; 5964 } 5965 if (!ctx->object) 5966 return len; 5967 action = &out->args.vc.actions[out->args.vc.actions_n - 1]; 5968 action_sample_data = ctx->object; 5969 idx = action_sample_data->idx; 5970 action_sample_data->conf.actions = raw_sample_confs[idx].data; 5971 action->conf = &action_sample_data->conf; 5972 return len; 5973 } 5974 5975 /** Parse tokens for destroy command. */ 5976 static int 5977 parse_destroy(struct context *ctx, const struct token *token, 5978 const char *str, unsigned int len, 5979 void *buf, unsigned int size) 5980 { 5981 struct buffer *out = buf; 5982 5983 /* Token name must match. */ 5984 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 5985 return -1; 5986 /* Nothing else to do if there is no buffer. */ 5987 if (!out) 5988 return len; 5989 if (!out->command) { 5990 if (ctx->curr != DESTROY) 5991 return -1; 5992 if (sizeof(*out) > size) 5993 return -1; 5994 out->command = ctx->curr; 5995 ctx->objdata = 0; 5996 ctx->object = out; 5997 ctx->objmask = NULL; 5998 out->args.destroy.rule = 5999 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 6000 sizeof(double)); 6001 return len; 6002 } 6003 if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) + 6004 sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size) 6005 return -1; 6006 ctx->objdata = 0; 6007 ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++; 6008 ctx->objmask = NULL; 6009 return len; 6010 } 6011 6012 /** Parse tokens for flush command. */ 6013 static int 6014 parse_flush(struct context *ctx, const struct token *token, 6015 const char *str, unsigned int len, 6016 void *buf, unsigned int size) 6017 { 6018 struct buffer *out = buf; 6019 6020 /* Token name must match. */ 6021 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6022 return -1; 6023 /* Nothing else to do if there is no buffer. */ 6024 if (!out) 6025 return len; 6026 if (!out->command) { 6027 if (ctx->curr != FLUSH) 6028 return -1; 6029 if (sizeof(*out) > size) 6030 return -1; 6031 out->command = ctx->curr; 6032 ctx->objdata = 0; 6033 ctx->object = out; 6034 ctx->objmask = NULL; 6035 } 6036 return len; 6037 } 6038 6039 /** Parse tokens for dump command. */ 6040 static int 6041 parse_dump(struct context *ctx, const struct token *token, 6042 const char *str, unsigned int len, 6043 void *buf, unsigned int size) 6044 { 6045 struct buffer *out = buf; 6046 6047 /* Token name must match. */ 6048 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6049 return -1; 6050 /* Nothing else to do if there is no buffer. */ 6051 if (!out) 6052 return len; 6053 if (!out->command) { 6054 if (ctx->curr != DUMP) 6055 return -1; 6056 if (sizeof(*out) > size) 6057 return -1; 6058 out->command = ctx->curr; 6059 ctx->objdata = 0; 6060 ctx->object = out; 6061 ctx->objmask = NULL; 6062 } 6063 return len; 6064 } 6065 6066 /** Parse tokens for query command. */ 6067 static int 6068 parse_query(struct context *ctx, const struct token *token, 6069 const char *str, unsigned int len, 6070 void *buf, unsigned int size) 6071 { 6072 struct buffer *out = buf; 6073 6074 /* Token name must match. */ 6075 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6076 return -1; 6077 /* Nothing else to do if there is no buffer. */ 6078 if (!out) 6079 return len; 6080 if (!out->command) { 6081 if (ctx->curr != QUERY) 6082 return -1; 6083 if (sizeof(*out) > size) 6084 return -1; 6085 out->command = ctx->curr; 6086 ctx->objdata = 0; 6087 ctx->object = out; 6088 ctx->objmask = NULL; 6089 } 6090 return len; 6091 } 6092 6093 /** Parse action names. */ 6094 static int 6095 parse_action(struct context *ctx, const struct token *token, 6096 const char *str, unsigned int len, 6097 void *buf, unsigned int size) 6098 { 6099 struct buffer *out = buf; 6100 const struct arg *arg = pop_args(ctx); 6101 unsigned int i; 6102 6103 (void)size; 6104 /* Argument is expected. */ 6105 if (!arg) 6106 return -1; 6107 /* Parse action name. */ 6108 for (i = 0; next_action[i]; ++i) { 6109 const struct parse_action_priv *priv; 6110 6111 token = &token_list[next_action[i]]; 6112 if (strcmp_partial(token->name, str, len)) 6113 continue; 6114 priv = token->priv; 6115 if (!priv) 6116 goto error; 6117 if (out) 6118 memcpy((uint8_t *)ctx->object + arg->offset, 6119 &priv->type, 6120 arg->size); 6121 return len; 6122 } 6123 error: 6124 push_args(ctx, arg); 6125 return -1; 6126 } 6127 6128 /** Parse tokens for list command. */ 6129 static int 6130 parse_list(struct context *ctx, const struct token *token, 6131 const char *str, unsigned int len, 6132 void *buf, unsigned int size) 6133 { 6134 struct buffer *out = buf; 6135 6136 /* Token name must match. */ 6137 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6138 return -1; 6139 /* Nothing else to do if there is no buffer. */ 6140 if (!out) 6141 return len; 6142 if (!out->command) { 6143 if (ctx->curr != LIST) 6144 return -1; 6145 if (sizeof(*out) > size) 6146 return -1; 6147 out->command = ctx->curr; 6148 ctx->objdata = 0; 6149 ctx->object = out; 6150 ctx->objmask = NULL; 6151 out->args.list.group = 6152 (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 6153 sizeof(double)); 6154 return len; 6155 } 6156 if (((uint8_t *)(out->args.list.group + out->args.list.group_n) + 6157 sizeof(*out->args.list.group)) > (uint8_t *)out + size) 6158 return -1; 6159 ctx->objdata = 0; 6160 ctx->object = out->args.list.group + out->args.list.group_n++; 6161 ctx->objmask = NULL; 6162 return len; 6163 } 6164 6165 /** Parse tokens for list all aged flows command. */ 6166 static int 6167 parse_aged(struct context *ctx, const struct token *token, 6168 const char *str, unsigned int len, 6169 void *buf, unsigned int size) 6170 { 6171 struct buffer *out = buf; 6172 6173 /* Token name must match. */ 6174 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6175 return -1; 6176 /* Nothing else to do if there is no buffer. */ 6177 if (!out) 6178 return len; 6179 if (!out->command) { 6180 if (ctx->curr != AGED) 6181 return -1; 6182 if (sizeof(*out) > size) 6183 return -1; 6184 out->command = ctx->curr; 6185 ctx->objdata = 0; 6186 ctx->object = out; 6187 ctx->objmask = NULL; 6188 } 6189 if (ctx->curr == AGED_DESTROY) 6190 out->args.aged.destroy = 1; 6191 return len; 6192 } 6193 6194 /** Parse tokens for isolate command. */ 6195 static int 6196 parse_isolate(struct context *ctx, const struct token *token, 6197 const char *str, unsigned int len, 6198 void *buf, unsigned int size) 6199 { 6200 struct buffer *out = buf; 6201 6202 /* Token name must match. */ 6203 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6204 return -1; 6205 /* Nothing else to do if there is no buffer. */ 6206 if (!out) 6207 return len; 6208 if (!out->command) { 6209 if (ctx->curr != ISOLATE) 6210 return -1; 6211 if (sizeof(*out) > size) 6212 return -1; 6213 out->command = ctx->curr; 6214 ctx->objdata = 0; 6215 ctx->object = out; 6216 ctx->objmask = NULL; 6217 } 6218 return len; 6219 } 6220 6221 static int 6222 parse_tunnel(struct context *ctx, const struct token *token, 6223 const char *str, unsigned int len, 6224 void *buf, unsigned int size) 6225 { 6226 struct buffer *out = buf; 6227 6228 /* Token name must match. */ 6229 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6230 return -1; 6231 /* Nothing else to do if there is no buffer. */ 6232 if (!out) 6233 return len; 6234 if (!out->command) { 6235 if (ctx->curr != TUNNEL) 6236 return -1; 6237 if (sizeof(*out) > size) 6238 return -1; 6239 out->command = ctx->curr; 6240 ctx->objdata = 0; 6241 ctx->object = out; 6242 ctx->objmask = NULL; 6243 } else { 6244 switch (ctx->curr) { 6245 default: 6246 break; 6247 case TUNNEL_CREATE: 6248 case TUNNEL_DESTROY: 6249 case TUNNEL_LIST: 6250 out->command = ctx->curr; 6251 break; 6252 case TUNNEL_CREATE_TYPE: 6253 case TUNNEL_DESTROY_ID: 6254 ctx->object = &out->args.vc.tunnel_ops; 6255 break; 6256 } 6257 } 6258 6259 return len; 6260 } 6261 6262 /** 6263 * Parse signed/unsigned integers 8 to 64-bit long. 6264 * 6265 * Last argument (ctx->args) is retrieved to determine integer type and 6266 * storage location. 6267 */ 6268 static int 6269 parse_int(struct context *ctx, const struct token *token, 6270 const char *str, unsigned int len, 6271 void *buf, unsigned int size) 6272 { 6273 const struct arg *arg = pop_args(ctx); 6274 uintmax_t u; 6275 char *end; 6276 6277 (void)token; 6278 /* Argument is expected. */ 6279 if (!arg) 6280 return -1; 6281 errno = 0; 6282 u = arg->sign ? 6283 (uintmax_t)strtoimax(str, &end, 0) : 6284 strtoumax(str, &end, 0); 6285 if (errno || (size_t)(end - str) != len) 6286 goto error; 6287 if (arg->bounded && 6288 ((arg->sign && ((intmax_t)u < (intmax_t)arg->min || 6289 (intmax_t)u > (intmax_t)arg->max)) || 6290 (!arg->sign && (u < arg->min || u > arg->max)))) 6291 goto error; 6292 if (!ctx->object) 6293 return len; 6294 if (arg->mask) { 6295 if (!arg_entry_bf_fill(ctx->object, u, arg) || 6296 !arg_entry_bf_fill(ctx->objmask, -1, arg)) 6297 goto error; 6298 return len; 6299 } 6300 buf = (uint8_t *)ctx->object + arg->offset; 6301 size = arg->size; 6302 if (u > RTE_LEN2MASK(size * CHAR_BIT, uint64_t)) 6303 return -1; 6304 objmask: 6305 switch (size) { 6306 case sizeof(uint8_t): 6307 *(uint8_t *)buf = u; 6308 break; 6309 case sizeof(uint16_t): 6310 *(uint16_t *)buf = arg->hton ? rte_cpu_to_be_16(u) : u; 6311 break; 6312 case sizeof(uint8_t [3]): 6313 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN 6314 if (!arg->hton) { 6315 ((uint8_t *)buf)[0] = u; 6316 ((uint8_t *)buf)[1] = u >> 8; 6317 ((uint8_t *)buf)[2] = u >> 16; 6318 break; 6319 } 6320 #endif 6321 ((uint8_t *)buf)[0] = u >> 16; 6322 ((uint8_t *)buf)[1] = u >> 8; 6323 ((uint8_t *)buf)[2] = u; 6324 break; 6325 case sizeof(uint32_t): 6326 *(uint32_t *)buf = arg->hton ? rte_cpu_to_be_32(u) : u; 6327 break; 6328 case sizeof(uint64_t): 6329 *(uint64_t *)buf = arg->hton ? rte_cpu_to_be_64(u) : u; 6330 break; 6331 default: 6332 goto error; 6333 } 6334 if (ctx->objmask && buf != (uint8_t *)ctx->objmask + arg->offset) { 6335 u = -1; 6336 buf = (uint8_t *)ctx->objmask + arg->offset; 6337 goto objmask; 6338 } 6339 return len; 6340 error: 6341 push_args(ctx, arg); 6342 return -1; 6343 } 6344 6345 /** 6346 * Parse a string. 6347 * 6348 * Three arguments (ctx->args) are retrieved from the stack to store data, 6349 * its actual length and address (in that order). 6350 */ 6351 static int 6352 parse_string(struct context *ctx, const struct token *token, 6353 const char *str, unsigned int len, 6354 void *buf, unsigned int size) 6355 { 6356 const struct arg *arg_data = pop_args(ctx); 6357 const struct arg *arg_len = pop_args(ctx); 6358 const struct arg *arg_addr = pop_args(ctx); 6359 char tmp[16]; /* Ought to be enough. */ 6360 int ret; 6361 6362 /* Arguments are expected. */ 6363 if (!arg_data) 6364 return -1; 6365 if (!arg_len) { 6366 push_args(ctx, arg_data); 6367 return -1; 6368 } 6369 if (!arg_addr) { 6370 push_args(ctx, arg_len); 6371 push_args(ctx, arg_data); 6372 return -1; 6373 } 6374 size = arg_data->size; 6375 /* Bit-mask fill is not supported. */ 6376 if (arg_data->mask || size < len) 6377 goto error; 6378 if (!ctx->object) 6379 return len; 6380 /* Let parse_int() fill length information first. */ 6381 ret = snprintf(tmp, sizeof(tmp), "%u", len); 6382 if (ret < 0) 6383 goto error; 6384 push_args(ctx, arg_len); 6385 ret = parse_int(ctx, token, tmp, ret, NULL, 0); 6386 if (ret < 0) { 6387 pop_args(ctx); 6388 goto error; 6389 } 6390 buf = (uint8_t *)ctx->object + arg_data->offset; 6391 /* Output buffer is not necessarily NUL-terminated. */ 6392 memcpy(buf, str, len); 6393 memset((uint8_t *)buf + len, 0x00, size - len); 6394 if (ctx->objmask) 6395 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len); 6396 /* Save address if requested. */ 6397 if (arg_addr->size) { 6398 memcpy((uint8_t *)ctx->object + arg_addr->offset, 6399 (void *[]){ 6400 (uint8_t *)ctx->object + arg_data->offset 6401 }, 6402 arg_addr->size); 6403 if (ctx->objmask) 6404 memcpy((uint8_t *)ctx->objmask + arg_addr->offset, 6405 (void *[]){ 6406 (uint8_t *)ctx->objmask + arg_data->offset 6407 }, 6408 arg_addr->size); 6409 } 6410 return len; 6411 error: 6412 push_args(ctx, arg_addr); 6413 push_args(ctx, arg_len); 6414 push_args(ctx, arg_data); 6415 return -1; 6416 } 6417 6418 static int 6419 parse_hex_string(const char *src, uint8_t *dst, uint32_t *size) 6420 { 6421 char *c = NULL; 6422 uint32_t i, len; 6423 char tmp[3]; 6424 6425 /* Check input parameters */ 6426 if ((src == NULL) || 6427 (dst == NULL) || 6428 (size == NULL) || 6429 (*size == 0)) 6430 return -1; 6431 6432 /* Convert chars to bytes */ 6433 for (i = 0, len = 0; i < *size; i += 2) { 6434 snprintf(tmp, 3, "%s", src + i); 6435 dst[len++] = strtoul(tmp, &c, 16); 6436 if (*c != 0) { 6437 len--; 6438 dst[len] = 0; 6439 *size = len; 6440 return -1; 6441 } 6442 } 6443 dst[len] = 0; 6444 *size = len; 6445 6446 return 0; 6447 } 6448 6449 static int 6450 parse_hex(struct context *ctx, const struct token *token, 6451 const char *str, unsigned int len, 6452 void *buf, unsigned int size) 6453 { 6454 const struct arg *arg_data = pop_args(ctx); 6455 const struct arg *arg_len = pop_args(ctx); 6456 const struct arg *arg_addr = pop_args(ctx); 6457 char tmp[16]; /* Ought to be enough. */ 6458 int ret; 6459 unsigned int hexlen = len; 6460 unsigned int length = 256; 6461 uint8_t hex_tmp[length]; 6462 6463 /* Arguments are expected. */ 6464 if (!arg_data) 6465 return -1; 6466 if (!arg_len) { 6467 push_args(ctx, arg_data); 6468 return -1; 6469 } 6470 if (!arg_addr) { 6471 push_args(ctx, arg_len); 6472 push_args(ctx, arg_data); 6473 return -1; 6474 } 6475 size = arg_data->size; 6476 /* Bit-mask fill is not supported. */ 6477 if (arg_data->mask) 6478 goto error; 6479 if (!ctx->object) 6480 return len; 6481 6482 /* translate bytes string to array. */ 6483 if (str[0] == '0' && ((str[1] == 'x') || 6484 (str[1] == 'X'))) { 6485 str += 2; 6486 hexlen -= 2; 6487 } 6488 if (hexlen > length) 6489 return -1; 6490 ret = parse_hex_string(str, hex_tmp, &hexlen); 6491 if (ret < 0) 6492 goto error; 6493 /* Let parse_int() fill length information first. */ 6494 ret = snprintf(tmp, sizeof(tmp), "%u", hexlen); 6495 if (ret < 0) 6496 goto error; 6497 push_args(ctx, arg_len); 6498 ret = parse_int(ctx, token, tmp, ret, NULL, 0); 6499 if (ret < 0) { 6500 pop_args(ctx); 6501 goto error; 6502 } 6503 buf = (uint8_t *)ctx->object + arg_data->offset; 6504 /* Output buffer is not necessarily NUL-terminated. */ 6505 memcpy(buf, hex_tmp, hexlen); 6506 memset((uint8_t *)buf + hexlen, 0x00, size - hexlen); 6507 if (ctx->objmask) 6508 memset((uint8_t *)ctx->objmask + arg_data->offset, 6509 0xff, hexlen); 6510 /* Save address if requested. */ 6511 if (arg_addr->size) { 6512 memcpy((uint8_t *)ctx->object + arg_addr->offset, 6513 (void *[]){ 6514 (uint8_t *)ctx->object + arg_data->offset 6515 }, 6516 arg_addr->size); 6517 if (ctx->objmask) 6518 memcpy((uint8_t *)ctx->objmask + arg_addr->offset, 6519 (void *[]){ 6520 (uint8_t *)ctx->objmask + arg_data->offset 6521 }, 6522 arg_addr->size); 6523 } 6524 return len; 6525 error: 6526 push_args(ctx, arg_addr); 6527 push_args(ctx, arg_len); 6528 push_args(ctx, arg_data); 6529 return -1; 6530 6531 } 6532 6533 /** 6534 * Parse a zero-ended string. 6535 */ 6536 static int 6537 parse_string0(struct context *ctx, const struct token *token __rte_unused, 6538 const char *str, unsigned int len, 6539 void *buf, unsigned int size) 6540 { 6541 const struct arg *arg_data = pop_args(ctx); 6542 6543 /* Arguments are expected. */ 6544 if (!arg_data) 6545 return -1; 6546 size = arg_data->size; 6547 /* Bit-mask fill is not supported. */ 6548 if (arg_data->mask || size < len + 1) 6549 goto error; 6550 if (!ctx->object) 6551 return len; 6552 buf = (uint8_t *)ctx->object + arg_data->offset; 6553 strncpy(buf, str, len); 6554 if (ctx->objmask) 6555 memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len); 6556 return len; 6557 error: 6558 push_args(ctx, arg_data); 6559 return -1; 6560 } 6561 6562 /** 6563 * Parse a MAC address. 6564 * 6565 * Last argument (ctx->args) is retrieved to determine storage size and 6566 * location. 6567 */ 6568 static int 6569 parse_mac_addr(struct context *ctx, const struct token *token, 6570 const char *str, unsigned int len, 6571 void *buf, unsigned int size) 6572 { 6573 const struct arg *arg = pop_args(ctx); 6574 struct rte_ether_addr tmp; 6575 int ret; 6576 6577 (void)token; 6578 /* Argument is expected. */ 6579 if (!arg) 6580 return -1; 6581 size = arg->size; 6582 /* Bit-mask fill is not supported. */ 6583 if (arg->mask || size != sizeof(tmp)) 6584 goto error; 6585 /* Only network endian is supported. */ 6586 if (!arg->hton) 6587 goto error; 6588 ret = cmdline_parse_etheraddr(NULL, str, &tmp, size); 6589 if (ret < 0 || (unsigned int)ret != len) 6590 goto error; 6591 if (!ctx->object) 6592 return len; 6593 buf = (uint8_t *)ctx->object + arg->offset; 6594 memcpy(buf, &tmp, size); 6595 if (ctx->objmask) 6596 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 6597 return len; 6598 error: 6599 push_args(ctx, arg); 6600 return -1; 6601 } 6602 6603 /** 6604 * Parse an IPv4 address. 6605 * 6606 * Last argument (ctx->args) is retrieved to determine storage size and 6607 * location. 6608 */ 6609 static int 6610 parse_ipv4_addr(struct context *ctx, const struct token *token, 6611 const char *str, unsigned int len, 6612 void *buf, unsigned int size) 6613 { 6614 const struct arg *arg = pop_args(ctx); 6615 char str2[len + 1]; 6616 struct in_addr tmp; 6617 int ret; 6618 6619 /* Argument is expected. */ 6620 if (!arg) 6621 return -1; 6622 size = arg->size; 6623 /* Bit-mask fill is not supported. */ 6624 if (arg->mask || size != sizeof(tmp)) 6625 goto error; 6626 /* Only network endian is supported. */ 6627 if (!arg->hton) 6628 goto error; 6629 memcpy(str2, str, len); 6630 str2[len] = '\0'; 6631 ret = inet_pton(AF_INET, str2, &tmp); 6632 if (ret != 1) { 6633 /* Attempt integer parsing. */ 6634 push_args(ctx, arg); 6635 return parse_int(ctx, token, str, len, buf, size); 6636 } 6637 if (!ctx->object) 6638 return len; 6639 buf = (uint8_t *)ctx->object + arg->offset; 6640 memcpy(buf, &tmp, size); 6641 if (ctx->objmask) 6642 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 6643 return len; 6644 error: 6645 push_args(ctx, arg); 6646 return -1; 6647 } 6648 6649 /** 6650 * Parse an IPv6 address. 6651 * 6652 * Last argument (ctx->args) is retrieved to determine storage size and 6653 * location. 6654 */ 6655 static int 6656 parse_ipv6_addr(struct context *ctx, const struct token *token, 6657 const char *str, unsigned int len, 6658 void *buf, unsigned int size) 6659 { 6660 const struct arg *arg = pop_args(ctx); 6661 char str2[len + 1]; 6662 struct in6_addr tmp; 6663 int ret; 6664 6665 (void)token; 6666 /* Argument is expected. */ 6667 if (!arg) 6668 return -1; 6669 size = arg->size; 6670 /* Bit-mask fill is not supported. */ 6671 if (arg->mask || size != sizeof(tmp)) 6672 goto error; 6673 /* Only network endian is supported. */ 6674 if (!arg->hton) 6675 goto error; 6676 memcpy(str2, str, len); 6677 str2[len] = '\0'; 6678 ret = inet_pton(AF_INET6, str2, &tmp); 6679 if (ret != 1) 6680 goto error; 6681 if (!ctx->object) 6682 return len; 6683 buf = (uint8_t *)ctx->object + arg->offset; 6684 memcpy(buf, &tmp, size); 6685 if (ctx->objmask) 6686 memset((uint8_t *)ctx->objmask + arg->offset, 0xff, size); 6687 return len; 6688 error: 6689 push_args(ctx, arg); 6690 return -1; 6691 } 6692 6693 /** Boolean values (even indices stand for false). */ 6694 static const char *const boolean_name[] = { 6695 "0", "1", 6696 "false", "true", 6697 "no", "yes", 6698 "N", "Y", 6699 "off", "on", 6700 NULL, 6701 }; 6702 6703 /** 6704 * Parse a boolean value. 6705 * 6706 * Last argument (ctx->args) is retrieved to determine storage size and 6707 * location. 6708 */ 6709 static int 6710 parse_boolean(struct context *ctx, const struct token *token, 6711 const char *str, unsigned int len, 6712 void *buf, unsigned int size) 6713 { 6714 const struct arg *arg = pop_args(ctx); 6715 unsigned int i; 6716 int ret; 6717 6718 /* Argument is expected. */ 6719 if (!arg) 6720 return -1; 6721 for (i = 0; boolean_name[i]; ++i) 6722 if (!strcmp_partial(boolean_name[i], str, len)) 6723 break; 6724 /* Process token as integer. */ 6725 if (boolean_name[i]) 6726 str = i & 1 ? "1" : "0"; 6727 push_args(ctx, arg); 6728 ret = parse_int(ctx, token, str, strlen(str), buf, size); 6729 return ret > 0 ? (int)len : ret; 6730 } 6731 6732 /** Parse port and update context. */ 6733 static int 6734 parse_port(struct context *ctx, const struct token *token, 6735 const char *str, unsigned int len, 6736 void *buf, unsigned int size) 6737 { 6738 struct buffer *out = &(struct buffer){ .port = 0 }; 6739 int ret; 6740 6741 if (buf) 6742 out = buf; 6743 else { 6744 ctx->objdata = 0; 6745 ctx->object = out; 6746 ctx->objmask = NULL; 6747 size = sizeof(*out); 6748 } 6749 ret = parse_int(ctx, token, str, len, out, size); 6750 if (ret >= 0) 6751 ctx->port = out->port; 6752 if (!buf) 6753 ctx->object = NULL; 6754 return ret; 6755 } 6756 6757 static int 6758 parse_sa_id2ptr(struct context *ctx, const struct token *token, 6759 const char *str, unsigned int len, 6760 void *buf, unsigned int size) 6761 { 6762 struct rte_flow_action *action = ctx->object; 6763 uint32_t id; 6764 int ret; 6765 6766 (void)buf; 6767 (void)size; 6768 ctx->objdata = 0; 6769 ctx->object = &id; 6770 ctx->objmask = NULL; 6771 ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id)); 6772 ctx->object = action; 6773 if (ret != (int)len) 6774 return ret; 6775 /* set shared action */ 6776 if (action) { 6777 action->conf = port_shared_action_get_by_id(ctx->port, id); 6778 ret = (action->conf) ? ret : -1; 6779 } 6780 return ret; 6781 } 6782 6783 /** Parse set command, initialize output buffer for subsequent tokens. */ 6784 static int 6785 parse_set_raw_encap_decap(struct context *ctx, const struct token *token, 6786 const char *str, unsigned int len, 6787 void *buf, unsigned int size) 6788 { 6789 struct buffer *out = buf; 6790 6791 /* Token name must match. */ 6792 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6793 return -1; 6794 /* Nothing else to do if there is no buffer. */ 6795 if (!out) 6796 return len; 6797 /* Make sure buffer is large enough. */ 6798 if (size < sizeof(*out)) 6799 return -1; 6800 ctx->objdata = 0; 6801 ctx->objmask = NULL; 6802 ctx->object = out; 6803 if (!out->command) 6804 return -1; 6805 out->command = ctx->curr; 6806 /* For encap/decap we need is pattern */ 6807 out->args.vc.pattern = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 6808 sizeof(double)); 6809 return len; 6810 } 6811 6812 /** Parse set command, initialize output buffer for subsequent tokens. */ 6813 static int 6814 parse_set_sample_action(struct context *ctx, const struct token *token, 6815 const char *str, unsigned int len, 6816 void *buf, unsigned int size) 6817 { 6818 struct buffer *out = buf; 6819 6820 /* Token name must match. */ 6821 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6822 return -1; 6823 /* Nothing else to do if there is no buffer. */ 6824 if (!out) 6825 return len; 6826 /* Make sure buffer is large enough. */ 6827 if (size < sizeof(*out)) 6828 return -1; 6829 ctx->objdata = 0; 6830 ctx->objmask = NULL; 6831 ctx->object = out; 6832 if (!out->command) 6833 return -1; 6834 out->command = ctx->curr; 6835 /* For sampler we need is actions */ 6836 out->args.vc.actions = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 6837 sizeof(double)); 6838 return len; 6839 } 6840 6841 /** 6842 * Parse set raw_encap/raw_decap command, 6843 * initialize output buffer for subsequent tokens. 6844 */ 6845 static int 6846 parse_set_init(struct context *ctx, const struct token *token, 6847 const char *str, unsigned int len, 6848 void *buf, unsigned int size) 6849 { 6850 struct buffer *out = buf; 6851 6852 /* Token name must match. */ 6853 if (parse_default(ctx, token, str, len, NULL, 0) < 0) 6854 return -1; 6855 /* Nothing else to do if there is no buffer. */ 6856 if (!out) 6857 return len; 6858 /* Make sure buffer is large enough. */ 6859 if (size < sizeof(*out)) 6860 return -1; 6861 /* Initialize buffer. */ 6862 memset(out, 0x00, sizeof(*out)); 6863 memset((uint8_t *)out + sizeof(*out), 0x22, size - sizeof(*out)); 6864 ctx->objdata = 0; 6865 ctx->object = out; 6866 ctx->objmask = NULL; 6867 if (!out->command) { 6868 if (ctx->curr != SET) 6869 return -1; 6870 if (sizeof(*out) > size) 6871 return -1; 6872 out->command = ctx->curr; 6873 out->args.vc.data = (uint8_t *)out + size; 6874 ctx->object = (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), 6875 sizeof(double)); 6876 } 6877 return len; 6878 } 6879 6880 /** No completion. */ 6881 static int 6882 comp_none(struct context *ctx, const struct token *token, 6883 unsigned int ent, char *buf, unsigned int size) 6884 { 6885 (void)ctx; 6886 (void)token; 6887 (void)ent; 6888 (void)buf; 6889 (void)size; 6890 return 0; 6891 } 6892 6893 /** Complete boolean values. */ 6894 static int 6895 comp_boolean(struct context *ctx, const struct token *token, 6896 unsigned int ent, char *buf, unsigned int size) 6897 { 6898 unsigned int i; 6899 6900 (void)ctx; 6901 (void)token; 6902 for (i = 0; boolean_name[i]; ++i) 6903 if (buf && i == ent) 6904 return strlcpy(buf, boolean_name[i], size); 6905 if (buf) 6906 return -1; 6907 return i; 6908 } 6909 6910 /** Complete action names. */ 6911 static int 6912 comp_action(struct context *ctx, const struct token *token, 6913 unsigned int ent, char *buf, unsigned int size) 6914 { 6915 unsigned int i; 6916 6917 (void)ctx; 6918 (void)token; 6919 for (i = 0; next_action[i]; ++i) 6920 if (buf && i == ent) 6921 return strlcpy(buf, token_list[next_action[i]].name, 6922 size); 6923 if (buf) 6924 return -1; 6925 return i; 6926 } 6927 6928 /** Complete available ports. */ 6929 static int 6930 comp_port(struct context *ctx, const struct token *token, 6931 unsigned int ent, char *buf, unsigned int size) 6932 { 6933 unsigned int i = 0; 6934 portid_t p; 6935 6936 (void)ctx; 6937 (void)token; 6938 RTE_ETH_FOREACH_DEV(p) { 6939 if (buf && i == ent) 6940 return snprintf(buf, size, "%u", p); 6941 ++i; 6942 } 6943 if (buf) 6944 return -1; 6945 return i; 6946 } 6947 6948 /** Complete available rule IDs. */ 6949 static int 6950 comp_rule_id(struct context *ctx, const struct token *token, 6951 unsigned int ent, char *buf, unsigned int size) 6952 { 6953 unsigned int i = 0; 6954 struct rte_port *port; 6955 struct port_flow *pf; 6956 6957 (void)token; 6958 if (port_id_is_invalid(ctx->port, DISABLED_WARN) || 6959 ctx->port == (portid_t)RTE_PORT_ALL) 6960 return -1; 6961 port = &ports[ctx->port]; 6962 for (pf = port->flow_list; pf != NULL; pf = pf->next) { 6963 if (buf && i == ent) 6964 return snprintf(buf, size, "%u", pf->id); 6965 ++i; 6966 } 6967 if (buf) 6968 return -1; 6969 return i; 6970 } 6971 6972 /** Complete type field for RSS action. */ 6973 static int 6974 comp_vc_action_rss_type(struct context *ctx, const struct token *token, 6975 unsigned int ent, char *buf, unsigned int size) 6976 { 6977 unsigned int i; 6978 6979 (void)ctx; 6980 (void)token; 6981 for (i = 0; rss_type_table[i].str; ++i) 6982 ; 6983 if (!buf) 6984 return i + 1; 6985 if (ent < i) 6986 return strlcpy(buf, rss_type_table[ent].str, size); 6987 if (ent == i) 6988 return snprintf(buf, size, "end"); 6989 return -1; 6990 } 6991 6992 /** Complete queue field for RSS action. */ 6993 static int 6994 comp_vc_action_rss_queue(struct context *ctx, const struct token *token, 6995 unsigned int ent, char *buf, unsigned int size) 6996 { 6997 (void)ctx; 6998 (void)token; 6999 if (!buf) 7000 return nb_rxq + 1; 7001 if (ent < nb_rxq) 7002 return snprintf(buf, size, "%u", ent); 7003 if (ent == nb_rxq) 7004 return snprintf(buf, size, "end"); 7005 return -1; 7006 } 7007 7008 /** Complete index number for set raw_encap/raw_decap commands. */ 7009 static int 7010 comp_set_raw_index(struct context *ctx, const struct token *token, 7011 unsigned int ent, char *buf, unsigned int size) 7012 { 7013 uint16_t idx = 0; 7014 uint16_t nb = 0; 7015 7016 RTE_SET_USED(ctx); 7017 RTE_SET_USED(token); 7018 for (idx = 0; idx < RAW_ENCAP_CONFS_MAX_NUM; ++idx) { 7019 if (buf && idx == ent) 7020 return snprintf(buf, size, "%u", idx); 7021 ++nb; 7022 } 7023 return nb; 7024 } 7025 7026 /** Complete index number for set raw_encap/raw_decap commands. */ 7027 static int 7028 comp_set_sample_index(struct context *ctx, const struct token *token, 7029 unsigned int ent, char *buf, unsigned int size) 7030 { 7031 uint16_t idx = 0; 7032 uint16_t nb = 0; 7033 7034 RTE_SET_USED(ctx); 7035 RTE_SET_USED(token); 7036 for (idx = 0; idx < RAW_SAMPLE_CONFS_MAX_NUM; ++idx) { 7037 if (buf && idx == ent) 7038 return snprintf(buf, size, "%u", idx); 7039 ++nb; 7040 } 7041 return nb; 7042 } 7043 7044 /** Internal context. */ 7045 static struct context cmd_flow_context; 7046 7047 /** Global parser instance (cmdline API). */ 7048 cmdline_parse_inst_t cmd_flow; 7049 cmdline_parse_inst_t cmd_set_raw; 7050 7051 /** Initialize context. */ 7052 static void 7053 cmd_flow_context_init(struct context *ctx) 7054 { 7055 /* A full memset() is not necessary. */ 7056 ctx->curr = ZERO; 7057 ctx->prev = ZERO; 7058 ctx->next_num = 0; 7059 ctx->args_num = 0; 7060 ctx->eol = 0; 7061 ctx->last = 0; 7062 ctx->port = 0; 7063 ctx->objdata = 0; 7064 ctx->object = NULL; 7065 ctx->objmask = NULL; 7066 } 7067 7068 /** Parse a token (cmdline API). */ 7069 static int 7070 cmd_flow_parse(cmdline_parse_token_hdr_t *hdr, const char *src, void *result, 7071 unsigned int size) 7072 { 7073 struct context *ctx = &cmd_flow_context; 7074 const struct token *token; 7075 const enum index *list; 7076 int len; 7077 int i; 7078 7079 (void)hdr; 7080 token = &token_list[ctx->curr]; 7081 /* Check argument length. */ 7082 ctx->eol = 0; 7083 ctx->last = 1; 7084 for (len = 0; src[len]; ++len) 7085 if (src[len] == '#' || isspace(src[len])) 7086 break; 7087 if (!len) 7088 return -1; 7089 /* Last argument and EOL detection. */ 7090 for (i = len; src[i]; ++i) 7091 if (src[i] == '#' || src[i] == '\r' || src[i] == '\n') 7092 break; 7093 else if (!isspace(src[i])) { 7094 ctx->last = 0; 7095 break; 7096 } 7097 for (; src[i]; ++i) 7098 if (src[i] == '\r' || src[i] == '\n') { 7099 ctx->eol = 1; 7100 break; 7101 } 7102 /* Initialize context if necessary. */ 7103 if (!ctx->next_num) { 7104 if (!token->next) 7105 return 0; 7106 ctx->next[ctx->next_num++] = token->next[0]; 7107 } 7108 /* Process argument through candidates. */ 7109 ctx->prev = ctx->curr; 7110 list = ctx->next[ctx->next_num - 1]; 7111 for (i = 0; list[i]; ++i) { 7112 const struct token *next = &token_list[list[i]]; 7113 int tmp; 7114 7115 ctx->curr = list[i]; 7116 if (next->call) 7117 tmp = next->call(ctx, next, src, len, result, size); 7118 else 7119 tmp = parse_default(ctx, next, src, len, result, size); 7120 if (tmp == -1 || tmp != len) 7121 continue; 7122 token = next; 7123 break; 7124 } 7125 if (!list[i]) 7126 return -1; 7127 --ctx->next_num; 7128 /* Push subsequent tokens if any. */ 7129 if (token->next) 7130 for (i = 0; token->next[i]; ++i) { 7131 if (ctx->next_num == RTE_DIM(ctx->next)) 7132 return -1; 7133 ctx->next[ctx->next_num++] = token->next[i]; 7134 } 7135 /* Push arguments if any. */ 7136 if (token->args) 7137 for (i = 0; token->args[i]; ++i) { 7138 if (ctx->args_num == RTE_DIM(ctx->args)) 7139 return -1; 7140 ctx->args[ctx->args_num++] = token->args[i]; 7141 } 7142 return len; 7143 } 7144 7145 /** Return number of completion entries (cmdline API). */ 7146 static int 7147 cmd_flow_complete_get_nb(cmdline_parse_token_hdr_t *hdr) 7148 { 7149 struct context *ctx = &cmd_flow_context; 7150 const struct token *token = &token_list[ctx->curr]; 7151 const enum index *list; 7152 int i; 7153 7154 (void)hdr; 7155 /* Count number of tokens in current list. */ 7156 if (ctx->next_num) 7157 list = ctx->next[ctx->next_num - 1]; 7158 else 7159 list = token->next[0]; 7160 for (i = 0; list[i]; ++i) 7161 ; 7162 if (!i) 7163 return 0; 7164 /* 7165 * If there is a single token, use its completion callback, otherwise 7166 * return the number of entries. 7167 */ 7168 token = &token_list[list[0]]; 7169 if (i == 1 && token->comp) { 7170 /* Save index for cmd_flow_get_help(). */ 7171 ctx->prev = list[0]; 7172 return token->comp(ctx, token, 0, NULL, 0); 7173 } 7174 return i; 7175 } 7176 7177 /** Return a completion entry (cmdline API). */ 7178 static int 7179 cmd_flow_complete_get_elt(cmdline_parse_token_hdr_t *hdr, int index, 7180 char *dst, unsigned int size) 7181 { 7182 struct context *ctx = &cmd_flow_context; 7183 const struct token *token = &token_list[ctx->curr]; 7184 const enum index *list; 7185 int i; 7186 7187 (void)hdr; 7188 /* Count number of tokens in current list. */ 7189 if (ctx->next_num) 7190 list = ctx->next[ctx->next_num - 1]; 7191 else 7192 list = token->next[0]; 7193 for (i = 0; list[i]; ++i) 7194 ; 7195 if (!i) 7196 return -1; 7197 /* If there is a single token, use its completion callback. */ 7198 token = &token_list[list[0]]; 7199 if (i == 1 && token->comp) { 7200 /* Save index for cmd_flow_get_help(). */ 7201 ctx->prev = list[0]; 7202 return token->comp(ctx, token, index, dst, size) < 0 ? -1 : 0; 7203 } 7204 /* Otherwise make sure the index is valid and use defaults. */ 7205 if (index >= i) 7206 return -1; 7207 token = &token_list[list[index]]; 7208 strlcpy(dst, token->name, size); 7209 /* Save index for cmd_flow_get_help(). */ 7210 ctx->prev = list[index]; 7211 return 0; 7212 } 7213 7214 /** Populate help strings for current token (cmdline API). */ 7215 static int 7216 cmd_flow_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, unsigned int size) 7217 { 7218 struct context *ctx = &cmd_flow_context; 7219 const struct token *token = &token_list[ctx->prev]; 7220 7221 (void)hdr; 7222 if (!size) 7223 return -1; 7224 /* Set token type and update global help with details. */ 7225 strlcpy(dst, (token->type ? token->type : "TOKEN"), size); 7226 if (token->help) 7227 cmd_flow.help_str = token->help; 7228 else 7229 cmd_flow.help_str = token->name; 7230 return 0; 7231 } 7232 7233 /** Token definition template (cmdline API). */ 7234 static struct cmdline_token_hdr cmd_flow_token_hdr = { 7235 .ops = &(struct cmdline_token_ops){ 7236 .parse = cmd_flow_parse, 7237 .complete_get_nb = cmd_flow_complete_get_nb, 7238 .complete_get_elt = cmd_flow_complete_get_elt, 7239 .get_help = cmd_flow_get_help, 7240 }, 7241 .offset = 0, 7242 }; 7243 7244 /** Populate the next dynamic token. */ 7245 static void 7246 cmd_flow_tok(cmdline_parse_token_hdr_t **hdr, 7247 cmdline_parse_token_hdr_t **hdr_inst) 7248 { 7249 struct context *ctx = &cmd_flow_context; 7250 7251 /* Always reinitialize context before requesting the first token. */ 7252 if (!(hdr_inst - cmd_flow.tokens)) 7253 cmd_flow_context_init(ctx); 7254 /* Return NULL when no more tokens are expected. */ 7255 if (!ctx->next_num && ctx->curr) { 7256 *hdr = NULL; 7257 return; 7258 } 7259 /* Determine if command should end here. */ 7260 if (ctx->eol && ctx->last && ctx->next_num) { 7261 const enum index *list = ctx->next[ctx->next_num - 1]; 7262 int i; 7263 7264 for (i = 0; list[i]; ++i) { 7265 if (list[i] != END) 7266 continue; 7267 *hdr = NULL; 7268 return; 7269 } 7270 } 7271 *hdr = &cmd_flow_token_hdr; 7272 } 7273 7274 /** Dispatch parsed buffer to function calls. */ 7275 static void 7276 cmd_flow_parsed(const struct buffer *in) 7277 { 7278 switch (in->command) { 7279 case SHARED_ACTION_CREATE: 7280 port_shared_action_create( 7281 in->port, in->args.vc.attr.group, 7282 &((const struct rte_flow_shared_action_conf) { 7283 .ingress = in->args.vc.attr.ingress, 7284 .egress = in->args.vc.attr.egress, 7285 }), 7286 in->args.vc.actions); 7287 break; 7288 case SHARED_ACTION_DESTROY: 7289 port_shared_action_destroy(in->port, 7290 in->args.sa_destroy.action_id_n, 7291 in->args.sa_destroy.action_id); 7292 break; 7293 case SHARED_ACTION_UPDATE: 7294 port_shared_action_update(in->port, in->args.vc.attr.group, 7295 in->args.vc.actions); 7296 break; 7297 case SHARED_ACTION_QUERY: 7298 port_shared_action_query(in->port, in->args.sa.action_id); 7299 break; 7300 case VALIDATE: 7301 port_flow_validate(in->port, &in->args.vc.attr, 7302 in->args.vc.pattern, in->args.vc.actions, 7303 &in->args.vc.tunnel_ops); 7304 break; 7305 case CREATE: 7306 port_flow_create(in->port, &in->args.vc.attr, 7307 in->args.vc.pattern, in->args.vc.actions, 7308 &in->args.vc.tunnel_ops); 7309 break; 7310 case DESTROY: 7311 port_flow_destroy(in->port, in->args.destroy.rule_n, 7312 in->args.destroy.rule); 7313 break; 7314 case FLUSH: 7315 port_flow_flush(in->port); 7316 break; 7317 case DUMP: 7318 port_flow_dump(in->port, in->args.dump.file); 7319 break; 7320 case QUERY: 7321 port_flow_query(in->port, in->args.query.rule, 7322 &in->args.query.action); 7323 break; 7324 case LIST: 7325 port_flow_list(in->port, in->args.list.group_n, 7326 in->args.list.group); 7327 break; 7328 case ISOLATE: 7329 port_flow_isolate(in->port, in->args.isolate.set); 7330 break; 7331 case AGED: 7332 port_flow_aged(in->port, in->args.aged.destroy); 7333 break; 7334 case TUNNEL_CREATE: 7335 port_flow_tunnel_create(in->port, &in->args.vc.tunnel_ops); 7336 break; 7337 case TUNNEL_DESTROY: 7338 port_flow_tunnel_destroy(in->port, in->args.vc.tunnel_ops.id); 7339 break; 7340 case TUNNEL_LIST: 7341 port_flow_tunnel_list(in->port); 7342 break; 7343 default: 7344 break; 7345 } 7346 } 7347 7348 /** Token generator and output processing callback (cmdline API). */ 7349 static void 7350 cmd_flow_cb(void *arg0, struct cmdline *cl, void *arg2) 7351 { 7352 if (cl == NULL) 7353 cmd_flow_tok(arg0, arg2); 7354 else 7355 cmd_flow_parsed(arg0); 7356 } 7357 7358 /** Global parser instance (cmdline API). */ 7359 cmdline_parse_inst_t cmd_flow = { 7360 .f = cmd_flow_cb, 7361 .data = NULL, /**< Unused. */ 7362 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */ 7363 .tokens = { 7364 NULL, 7365 }, /**< Tokens are returned by cmd_flow_tok(). */ 7366 }; 7367 7368 /** set cmd facility. Reuse cmd flow's infrastructure as much as possible. */ 7369 7370 static void 7371 update_fields(uint8_t *buf, struct rte_flow_item *item, uint16_t next_proto) 7372 { 7373 struct rte_flow_item_ipv4 *ipv4; 7374 struct rte_flow_item_eth *eth; 7375 struct rte_flow_item_ipv6 *ipv6; 7376 struct rte_flow_item_vxlan *vxlan; 7377 struct rte_flow_item_vxlan_gpe *gpe; 7378 struct rte_flow_item_nvgre *nvgre; 7379 uint32_t ipv6_vtc_flow; 7380 7381 switch (item->type) { 7382 case RTE_FLOW_ITEM_TYPE_ETH: 7383 eth = (struct rte_flow_item_eth *)buf; 7384 if (next_proto) 7385 eth->type = rte_cpu_to_be_16(next_proto); 7386 break; 7387 case RTE_FLOW_ITEM_TYPE_IPV4: 7388 ipv4 = (struct rte_flow_item_ipv4 *)buf; 7389 ipv4->hdr.version_ihl = 0x45; 7390 if (next_proto && ipv4->hdr.next_proto_id == 0) 7391 ipv4->hdr.next_proto_id = (uint8_t)next_proto; 7392 break; 7393 case RTE_FLOW_ITEM_TYPE_IPV6: 7394 ipv6 = (struct rte_flow_item_ipv6 *)buf; 7395 if (next_proto && ipv6->hdr.proto == 0) 7396 ipv6->hdr.proto = (uint8_t)next_proto; 7397 ipv6_vtc_flow = rte_be_to_cpu_32(ipv6->hdr.vtc_flow); 7398 ipv6_vtc_flow &= 0x0FFFFFFF; /*< reset version bits. */ 7399 ipv6_vtc_flow |= 0x60000000; /*< set ipv6 version. */ 7400 ipv6->hdr.vtc_flow = rte_cpu_to_be_32(ipv6_vtc_flow); 7401 break; 7402 case RTE_FLOW_ITEM_TYPE_VXLAN: 7403 vxlan = (struct rte_flow_item_vxlan *)buf; 7404 vxlan->flags = 0x08; 7405 break; 7406 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 7407 gpe = (struct rte_flow_item_vxlan_gpe *)buf; 7408 gpe->flags = 0x0C; 7409 break; 7410 case RTE_FLOW_ITEM_TYPE_NVGRE: 7411 nvgre = (struct rte_flow_item_nvgre *)buf; 7412 nvgre->protocol = rte_cpu_to_be_16(0x6558); 7413 nvgre->c_k_s_rsvd0_ver = rte_cpu_to_be_16(0x2000); 7414 break; 7415 default: 7416 break; 7417 } 7418 } 7419 7420 /** Helper of get item's default mask. */ 7421 static const void * 7422 flow_item_default_mask(const struct rte_flow_item *item) 7423 { 7424 const void *mask = NULL; 7425 static rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX); 7426 7427 switch (item->type) { 7428 case RTE_FLOW_ITEM_TYPE_ANY: 7429 mask = &rte_flow_item_any_mask; 7430 break; 7431 case RTE_FLOW_ITEM_TYPE_VF: 7432 mask = &rte_flow_item_vf_mask; 7433 break; 7434 case RTE_FLOW_ITEM_TYPE_PORT_ID: 7435 mask = &rte_flow_item_port_id_mask; 7436 break; 7437 case RTE_FLOW_ITEM_TYPE_RAW: 7438 mask = &rte_flow_item_raw_mask; 7439 break; 7440 case RTE_FLOW_ITEM_TYPE_ETH: 7441 mask = &rte_flow_item_eth_mask; 7442 break; 7443 case RTE_FLOW_ITEM_TYPE_VLAN: 7444 mask = &rte_flow_item_vlan_mask; 7445 break; 7446 case RTE_FLOW_ITEM_TYPE_IPV4: 7447 mask = &rte_flow_item_ipv4_mask; 7448 break; 7449 case RTE_FLOW_ITEM_TYPE_IPV6: 7450 mask = &rte_flow_item_ipv6_mask; 7451 break; 7452 case RTE_FLOW_ITEM_TYPE_ICMP: 7453 mask = &rte_flow_item_icmp_mask; 7454 break; 7455 case RTE_FLOW_ITEM_TYPE_UDP: 7456 mask = &rte_flow_item_udp_mask; 7457 break; 7458 case RTE_FLOW_ITEM_TYPE_TCP: 7459 mask = &rte_flow_item_tcp_mask; 7460 break; 7461 case RTE_FLOW_ITEM_TYPE_SCTP: 7462 mask = &rte_flow_item_sctp_mask; 7463 break; 7464 case RTE_FLOW_ITEM_TYPE_VXLAN: 7465 mask = &rte_flow_item_vxlan_mask; 7466 break; 7467 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 7468 mask = &rte_flow_item_vxlan_gpe_mask; 7469 break; 7470 case RTE_FLOW_ITEM_TYPE_E_TAG: 7471 mask = &rte_flow_item_e_tag_mask; 7472 break; 7473 case RTE_FLOW_ITEM_TYPE_NVGRE: 7474 mask = &rte_flow_item_nvgre_mask; 7475 break; 7476 case RTE_FLOW_ITEM_TYPE_MPLS: 7477 mask = &rte_flow_item_mpls_mask; 7478 break; 7479 case RTE_FLOW_ITEM_TYPE_GRE: 7480 mask = &rte_flow_item_gre_mask; 7481 break; 7482 case RTE_FLOW_ITEM_TYPE_GRE_KEY: 7483 mask = &gre_key_default_mask; 7484 break; 7485 case RTE_FLOW_ITEM_TYPE_META: 7486 mask = &rte_flow_item_meta_mask; 7487 break; 7488 case RTE_FLOW_ITEM_TYPE_FUZZY: 7489 mask = &rte_flow_item_fuzzy_mask; 7490 break; 7491 case RTE_FLOW_ITEM_TYPE_GTP: 7492 mask = &rte_flow_item_gtp_mask; 7493 break; 7494 case RTE_FLOW_ITEM_TYPE_GTP_PSC: 7495 mask = &rte_flow_item_gtp_psc_mask; 7496 break; 7497 case RTE_FLOW_ITEM_TYPE_GENEVE: 7498 mask = &rte_flow_item_geneve_mask; 7499 break; 7500 case RTE_FLOW_ITEM_TYPE_PPPOE_PROTO_ID: 7501 mask = &rte_flow_item_pppoe_proto_id_mask; 7502 break; 7503 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP: 7504 mask = &rte_flow_item_l2tpv3oip_mask; 7505 break; 7506 case RTE_FLOW_ITEM_TYPE_ESP: 7507 mask = &rte_flow_item_esp_mask; 7508 break; 7509 case RTE_FLOW_ITEM_TYPE_AH: 7510 mask = &rte_flow_item_ah_mask; 7511 break; 7512 case RTE_FLOW_ITEM_TYPE_PFCP: 7513 mask = &rte_flow_item_pfcp_mask; 7514 break; 7515 default: 7516 break; 7517 } 7518 return mask; 7519 } 7520 7521 /** Dispatch parsed buffer to function calls. */ 7522 static void 7523 cmd_set_raw_parsed_sample(const struct buffer *in) 7524 { 7525 uint32_t n = in->args.vc.actions_n; 7526 uint32_t i = 0; 7527 struct rte_flow_action *action = NULL; 7528 struct rte_flow_action *data = NULL; 7529 size_t size = 0; 7530 uint16_t idx = in->port; /* We borrow port field as index */ 7531 uint32_t max_size = sizeof(struct rte_flow_action) * 7532 ACTION_SAMPLE_ACTIONS_NUM; 7533 7534 RTE_ASSERT(in->command == SET_SAMPLE_ACTIONS); 7535 data = (struct rte_flow_action *)&raw_sample_confs[idx].data; 7536 memset(data, 0x00, max_size); 7537 for (; i <= n - 1; i++) { 7538 action = in->args.vc.actions + i; 7539 if (action->type == RTE_FLOW_ACTION_TYPE_END) 7540 break; 7541 switch (action->type) { 7542 case RTE_FLOW_ACTION_TYPE_MARK: 7543 size = sizeof(struct rte_flow_action_mark); 7544 rte_memcpy(&sample_mark[idx], 7545 (const void *)action->conf, size); 7546 action->conf = &sample_mark[idx]; 7547 break; 7548 case RTE_FLOW_ACTION_TYPE_COUNT: 7549 size = sizeof(struct rte_flow_action_count); 7550 rte_memcpy(&sample_count[idx], 7551 (const void *)action->conf, size); 7552 action->conf = &sample_count[idx]; 7553 break; 7554 case RTE_FLOW_ACTION_TYPE_QUEUE: 7555 size = sizeof(struct rte_flow_action_queue); 7556 rte_memcpy(&sample_queue[idx], 7557 (const void *)action->conf, size); 7558 action->conf = &sample_queue[idx]; 7559 break; 7560 case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: 7561 size = sizeof(struct rte_flow_action_raw_encap); 7562 rte_memcpy(&sample_encap[idx], 7563 (const void *)action->conf, size); 7564 action->conf = &sample_encap[idx]; 7565 break; 7566 case RTE_FLOW_ACTION_TYPE_PORT_ID: 7567 size = sizeof(struct rte_flow_action_port_id); 7568 rte_memcpy(&sample_port_id[idx], 7569 (const void *)action->conf, size); 7570 action->conf = &sample_port_id[idx]; 7571 break; 7572 default: 7573 printf("Error - Not supported action\n"); 7574 return; 7575 } 7576 rte_memcpy(data, action, sizeof(struct rte_flow_action)); 7577 data++; 7578 } 7579 } 7580 7581 /** Dispatch parsed buffer to function calls. */ 7582 static void 7583 cmd_set_raw_parsed(const struct buffer *in) 7584 { 7585 uint32_t n = in->args.vc.pattern_n; 7586 int i = 0; 7587 struct rte_flow_item *item = NULL; 7588 size_t size = 0; 7589 uint8_t *data = NULL; 7590 uint8_t *data_tail = NULL; 7591 size_t *total_size = NULL; 7592 uint16_t upper_layer = 0; 7593 uint16_t proto = 0; 7594 uint16_t idx = in->port; /* We borrow port field as index */ 7595 7596 if (in->command == SET_SAMPLE_ACTIONS) 7597 return cmd_set_raw_parsed_sample(in); 7598 RTE_ASSERT(in->command == SET_RAW_ENCAP || 7599 in->command == SET_RAW_DECAP); 7600 if (in->command == SET_RAW_ENCAP) { 7601 total_size = &raw_encap_confs[idx].size; 7602 data = (uint8_t *)&raw_encap_confs[idx].data; 7603 } else { 7604 total_size = &raw_decap_confs[idx].size; 7605 data = (uint8_t *)&raw_decap_confs[idx].data; 7606 } 7607 *total_size = 0; 7608 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA); 7609 /* process hdr from upper layer to low layer (L3/L4 -> L2). */ 7610 data_tail = data + ACTION_RAW_ENCAP_MAX_DATA; 7611 for (i = n - 1 ; i >= 0; --i) { 7612 item = in->args.vc.pattern + i; 7613 if (item->spec == NULL) 7614 item->spec = flow_item_default_mask(item); 7615 switch (item->type) { 7616 case RTE_FLOW_ITEM_TYPE_ETH: 7617 size = sizeof(struct rte_flow_item_eth); 7618 break; 7619 case RTE_FLOW_ITEM_TYPE_VLAN: 7620 size = sizeof(struct rte_flow_item_vlan); 7621 proto = RTE_ETHER_TYPE_VLAN; 7622 break; 7623 case RTE_FLOW_ITEM_TYPE_IPV4: 7624 size = sizeof(struct rte_flow_item_ipv4); 7625 proto = RTE_ETHER_TYPE_IPV4; 7626 break; 7627 case RTE_FLOW_ITEM_TYPE_IPV6: 7628 size = sizeof(struct rte_flow_item_ipv6); 7629 proto = RTE_ETHER_TYPE_IPV6; 7630 break; 7631 case RTE_FLOW_ITEM_TYPE_UDP: 7632 size = sizeof(struct rte_flow_item_udp); 7633 proto = 0x11; 7634 break; 7635 case RTE_FLOW_ITEM_TYPE_TCP: 7636 size = sizeof(struct rte_flow_item_tcp); 7637 proto = 0x06; 7638 break; 7639 case RTE_FLOW_ITEM_TYPE_VXLAN: 7640 size = sizeof(struct rte_flow_item_vxlan); 7641 break; 7642 case RTE_FLOW_ITEM_TYPE_VXLAN_GPE: 7643 size = sizeof(struct rte_flow_item_vxlan_gpe); 7644 break; 7645 case RTE_FLOW_ITEM_TYPE_GRE: 7646 size = sizeof(struct rte_flow_item_gre); 7647 proto = 0x2F; 7648 break; 7649 case RTE_FLOW_ITEM_TYPE_GRE_KEY: 7650 size = sizeof(rte_be32_t); 7651 proto = 0x0; 7652 break; 7653 case RTE_FLOW_ITEM_TYPE_MPLS: 7654 size = sizeof(struct rte_flow_item_mpls); 7655 proto = 0x0; 7656 break; 7657 case RTE_FLOW_ITEM_TYPE_NVGRE: 7658 size = sizeof(struct rte_flow_item_nvgre); 7659 proto = 0x2F; 7660 break; 7661 case RTE_FLOW_ITEM_TYPE_GENEVE: 7662 size = sizeof(struct rte_flow_item_geneve); 7663 break; 7664 case RTE_FLOW_ITEM_TYPE_L2TPV3OIP: 7665 size = sizeof(struct rte_flow_item_l2tpv3oip); 7666 proto = 0x73; 7667 break; 7668 case RTE_FLOW_ITEM_TYPE_ESP: 7669 size = sizeof(struct rte_flow_item_esp); 7670 proto = 0x32; 7671 break; 7672 case RTE_FLOW_ITEM_TYPE_AH: 7673 size = sizeof(struct rte_flow_item_ah); 7674 proto = 0x33; 7675 break; 7676 case RTE_FLOW_ITEM_TYPE_GTP: 7677 size = sizeof(struct rte_flow_item_gtp); 7678 break; 7679 case RTE_FLOW_ITEM_TYPE_PFCP: 7680 size = sizeof(struct rte_flow_item_pfcp); 7681 break; 7682 default: 7683 printf("Error - Not supported item\n"); 7684 *total_size = 0; 7685 memset(data, 0x00, ACTION_RAW_ENCAP_MAX_DATA); 7686 return; 7687 } 7688 *total_size += size; 7689 rte_memcpy(data_tail - (*total_size), item->spec, size); 7690 /* update some fields which cannot be set by cmdline */ 7691 update_fields((data_tail - (*total_size)), item, 7692 upper_layer); 7693 upper_layer = proto; 7694 } 7695 if (verbose_level & 0x1) 7696 printf("total data size is %zu\n", (*total_size)); 7697 RTE_ASSERT((*total_size) <= ACTION_RAW_ENCAP_MAX_DATA); 7698 memmove(data, (data_tail - (*total_size)), *total_size); 7699 } 7700 7701 /** Populate help strings for current token (cmdline API). */ 7702 static int 7703 cmd_set_raw_get_help(cmdline_parse_token_hdr_t *hdr, char *dst, 7704 unsigned int size) 7705 { 7706 struct context *ctx = &cmd_flow_context; 7707 const struct token *token = &token_list[ctx->prev]; 7708 7709 (void)hdr; 7710 if (!size) 7711 return -1; 7712 /* Set token type and update global help with details. */ 7713 snprintf(dst, size, "%s", (token->type ? token->type : "TOKEN")); 7714 if (token->help) 7715 cmd_set_raw.help_str = token->help; 7716 else 7717 cmd_set_raw.help_str = token->name; 7718 return 0; 7719 } 7720 7721 /** Token definition template (cmdline API). */ 7722 static struct cmdline_token_hdr cmd_set_raw_token_hdr = { 7723 .ops = &(struct cmdline_token_ops){ 7724 .parse = cmd_flow_parse, 7725 .complete_get_nb = cmd_flow_complete_get_nb, 7726 .complete_get_elt = cmd_flow_complete_get_elt, 7727 .get_help = cmd_set_raw_get_help, 7728 }, 7729 .offset = 0, 7730 }; 7731 7732 /** Populate the next dynamic token. */ 7733 static void 7734 cmd_set_raw_tok(cmdline_parse_token_hdr_t **hdr, 7735 cmdline_parse_token_hdr_t **hdr_inst) 7736 { 7737 struct context *ctx = &cmd_flow_context; 7738 7739 /* Always reinitialize context before requesting the first token. */ 7740 if (!(hdr_inst - cmd_set_raw.tokens)) { 7741 cmd_flow_context_init(ctx); 7742 ctx->curr = START_SET; 7743 } 7744 /* Return NULL when no more tokens are expected. */ 7745 if (!ctx->next_num && (ctx->curr != START_SET)) { 7746 *hdr = NULL; 7747 return; 7748 } 7749 /* Determine if command should end here. */ 7750 if (ctx->eol && ctx->last && ctx->next_num) { 7751 const enum index *list = ctx->next[ctx->next_num - 1]; 7752 int i; 7753 7754 for (i = 0; list[i]; ++i) { 7755 if (list[i] != END) 7756 continue; 7757 *hdr = NULL; 7758 return; 7759 } 7760 } 7761 *hdr = &cmd_set_raw_token_hdr; 7762 } 7763 7764 /** Token generator and output processing callback (cmdline API). */ 7765 static void 7766 cmd_set_raw_cb(void *arg0, struct cmdline *cl, void *arg2) 7767 { 7768 if (cl == NULL) 7769 cmd_set_raw_tok(arg0, arg2); 7770 else 7771 cmd_set_raw_parsed(arg0); 7772 } 7773 7774 /** Global parser instance (cmdline API). */ 7775 cmdline_parse_inst_t cmd_set_raw = { 7776 .f = cmd_set_raw_cb, 7777 .data = NULL, /**< Unused. */ 7778 .help_str = NULL, /**< Updated by cmd_flow_get_help(). */ 7779 .tokens = { 7780 NULL, 7781 }, /**< Tokens are returned by cmd_flow_tok(). */ 7782 }; 7783 7784 /* *** display raw_encap/raw_decap buf */ 7785 struct cmd_show_set_raw_result { 7786 cmdline_fixed_string_t cmd_show; 7787 cmdline_fixed_string_t cmd_what; 7788 cmdline_fixed_string_t cmd_all; 7789 uint16_t cmd_index; 7790 }; 7791 7792 static void 7793 cmd_show_set_raw_parsed(void *parsed_result, struct cmdline *cl, void *data) 7794 { 7795 struct cmd_show_set_raw_result *res = parsed_result; 7796 uint16_t index = res->cmd_index; 7797 uint8_t all = 0; 7798 uint8_t *raw_data = NULL; 7799 size_t raw_size = 0; 7800 char title[16] = {0}; 7801 7802 RTE_SET_USED(cl); 7803 RTE_SET_USED(data); 7804 if (!strcmp(res->cmd_all, "all")) { 7805 all = 1; 7806 index = 0; 7807 } else if (index >= RAW_ENCAP_CONFS_MAX_NUM) { 7808 printf("index should be 0-%u\n", RAW_ENCAP_CONFS_MAX_NUM - 1); 7809 return; 7810 } 7811 do { 7812 if (!strcmp(res->cmd_what, "raw_encap")) { 7813 raw_data = (uint8_t *)&raw_encap_confs[index].data; 7814 raw_size = raw_encap_confs[index].size; 7815 snprintf(title, 16, "\nindex: %u", index); 7816 rte_hexdump(stdout, title, raw_data, raw_size); 7817 } else { 7818 raw_data = (uint8_t *)&raw_decap_confs[index].data; 7819 raw_size = raw_decap_confs[index].size; 7820 snprintf(title, 16, "\nindex: %u", index); 7821 rte_hexdump(stdout, title, raw_data, raw_size); 7822 } 7823 } while (all && ++index < RAW_ENCAP_CONFS_MAX_NUM); 7824 } 7825 7826 cmdline_parse_token_string_t cmd_show_set_raw_cmd_show = 7827 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, 7828 cmd_show, "show"); 7829 cmdline_parse_token_string_t cmd_show_set_raw_cmd_what = 7830 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, 7831 cmd_what, "raw_encap#raw_decap"); 7832 cmdline_parse_token_num_t cmd_show_set_raw_cmd_index = 7833 TOKEN_NUM_INITIALIZER(struct cmd_show_set_raw_result, 7834 cmd_index, UINT16); 7835 cmdline_parse_token_string_t cmd_show_set_raw_cmd_all = 7836 TOKEN_STRING_INITIALIZER(struct cmd_show_set_raw_result, 7837 cmd_all, "all"); 7838 cmdline_parse_inst_t cmd_show_set_raw = { 7839 .f = cmd_show_set_raw_parsed, 7840 .data = NULL, 7841 .help_str = "show <raw_encap|raw_decap> <index>", 7842 .tokens = { 7843 (void *)&cmd_show_set_raw_cmd_show, 7844 (void *)&cmd_show_set_raw_cmd_what, 7845 (void *)&cmd_show_set_raw_cmd_index, 7846 NULL, 7847 }, 7848 }; 7849 cmdline_parse_inst_t cmd_show_set_raw_all = { 7850 .f = cmd_show_set_raw_parsed, 7851 .data = NULL, 7852 .help_str = "show <raw_encap|raw_decap> all", 7853 .tokens = { 7854 (void *)&cmd_show_set_raw_cmd_show, 7855 (void *)&cmd_show_set_raw_cmd_what, 7856 (void *)&cmd_show_set_raw_cmd_all, 7857 NULL, 7858 }, 7859 }; 7860