From patchwork Fri Oct 15 09:58:21 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jie Wang X-Patchwork-Id: 101752 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 922D0A0C4B; Fri, 15 Oct 2021 11:58:52 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7C6E4411F6; Fri, 15 Oct 2021 11:58:52 +0200 (CEST) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by mails.dpdk.org (Postfix) with ESMTP id B3DC640692 for ; Fri, 15 Oct 2021 11:58:50 +0200 (CEST) X-IronPort-AV: E=McAfee;i="6200,9189,10137"; a="208000580" X-IronPort-AV: E=Sophos;i="5.85,375,1624345200"; d="scan'208";a="208000580" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Oct 2021 02:58:49 -0700 X-IronPort-AV: E=Sophos;i="5.85,375,1624345200"; d="scan'208";a="492394808" Received: from dpdk.cd.intel.com ([10.240.178.133]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Oct 2021 02:58:45 -0700 From: Jie Wang To: dev@dpdk.org Cc: orika@nvidia.com, ferruh.yigit@intel.com, thomas@monjalon.net, andrew.rybchenko@oktetlabs.ru, xiaoyun.li@intel.com, stevex.yang@intel.com, jingjing.wu@intel.com, beilei.xing@intel.com, wenjun1.wu@intel.com, Jie Wang Date: Fri, 15 Oct 2021 17:58:21 +0800 Message-Id: <20211015095823.701188-2-jie1x.wang@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211015095823.701188-1-jie1x.wang@intel.com> References: <20211012102508.275790-1-jie1x.wang@intel.com> <20211015095823.701188-1-jie1x.wang@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v3 1/3] ethdev: support PPP and L2TPV2 procotol X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Added flow pattern items and header formats of L2TPv2 and PPP to support PPP over L2TPv2 over UDP protocol RSS Hash. Signed-off-by: Wenjun Wu Signed-off-by: Jie Wang --- doc/guides/prog_guide/rte_flow.rst | 25 +++ doc/guides/rel_notes/release_21_11.rst | 5 + lib/ethdev/rte_flow.c | 2 + lib/ethdev/rte_flow.h | 117 ++++++++++++++ lib/net/rte_l2tpv2.h | 214 +++++++++++++++++++++++++ 5 files changed, 363 insertions(+) create mode 100644 lib/net/rte_l2tpv2.h diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst index 3cb014c1fa..59fe7e79b5 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -1425,6 +1425,31 @@ Matches a conntrack state after conntrack action. - ``flags``: conntrack packet state flags. - Default ``mask`` matches all state bits. +Item: ``L2TPV2`` +^^^^^^^^^^^^^^^^^^^ + +Matches a L2TPv2 header. + +- ``flags_version``: flags(12b), version(4b). +- ``length``: total length of the message. +- ``tunnel_id``: identifier for the control connection. +- ``session_id``: identifier for a session within a tunnel. +- ``ns``: sequence number for this date or control message. +- ``nr``: sequence number expected in the next control message to be received. +- ``offset_size``: offset of payload data. +- ``offset_padding``: offset padding, variable length. +- Default ``mask`` matches flags_version only. + +Item: ``PPP`` +^^^^^^^^^^^^^^^^^^^ + +Matches a PPP header. + +- ``addr``: ppp address. +- ``ctrl``: ppp control. +- ``proto_id``: ppp protocol identifier. +- Default ``mask`` matches addr, ctrl, proto_id. + Actions ~~~~~~~ diff --git a/doc/guides/rel_notes/release_21_11.rst b/doc/guides/rel_notes/release_21_11.rst index d5c762df62..503f6dd828 100644 --- a/doc/guides/rel_notes/release_21_11.rst +++ b/doc/guides/rel_notes/release_21_11.rst @@ -81,6 +81,11 @@ New Features * Default VLAN strip behavior was changed. VLAN tag won't be stripped unless ``DEV_RX_OFFLOAD_VLAN_STRIP`` offload is enabled. +* **Added L2TPV2 and PPP protocol support in rte_flow.** + + Added flow pattern items and header formats of L2TPv2 and PPP to support + PPP over L2TPv2 over UDP protocol RSS Hash. + * **Updated AF_XDP PMD.** * Disabled secondary process support. diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index 8cb7a069c8..1ec739a031 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -100,6 +100,8 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = { MK_FLOW_ITEM(GENEVE_OPT, sizeof(struct rte_flow_item_geneve_opt)), MK_FLOW_ITEM(INTEGRITY, sizeof(struct rte_flow_item_integrity)), MK_FLOW_ITEM(CONNTRACK, sizeof(uint32_t)), + MK_FLOW_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)), + MK_FLOW_ITEM(PPP, sizeof(struct rte_flow_item_ppp)), }; /** Generate flow_action[] entry. */ diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index 5f87851f8c..f8fcf9c1f8 100644 --- a/lib/ethdev/rte_flow.h +++ b/lib/ethdev/rte_flow.h @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -574,6 +575,21 @@ enum rte_flow_item_type { * @see struct rte_flow_item_conntrack. */ RTE_FLOW_ITEM_TYPE_CONNTRACK, + + /** + * Matches L2TPV2 Header. + * + * See struct rte_flow_item_l2tpv2. + */ + RTE_FLOW_ITEM_TYPE_L2TPV2, + + /** + * Matches PPP Header. + * + * See struct rte_flow_item_ppp. + */ + RTE_FLOW_ITEM_TYPE_PPP, + }; /** @@ -1799,6 +1815,55 @@ static const struct rte_flow_item_conntrack rte_flow_item_conntrack_mask = { }; #endif +/** + * @warning + * @b EXPERIMENTAL: this structure may change without prior notice + * RTE_FLOW_ITEM_TYPE_L2TPV2 + * + * Matches L2TPv2 Header + */ +struct rte_flow_item_l2tpv2 { + struct rte_l2tpv2_combined_msg_hdr hdr; +}; + +/** Default mask for RTE_FLOW_ITEM_TYPE_L2TPV2. */ +#ifndef __cplusplus +static const struct rte_flow_item_l2tpv2 rte_flow_item_l2tpv2_mask = { + /* + * flags and version bit mask + * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 + * T L x x S x O P x x x x V V V V + */ + .hdr = { + .common = { + .flags_version = 0xcb0f, + }, + }, +}; +#endif + +/** + * @warning + * @b EXPERIMENTAL: this structure may change without prior notice + * RTE_FLOW_ITEM_TYPE_PPP + * + * Matches PPP Header + */ +struct rte_flow_item_ppp { + uint8_t addr; /**< ppp address(8) */ + uint8_t ctrl; /**< ppp control(8) */ + rte_be16_t proto_id; /**< ppp protocol id(16) */ +}; + +/** Default mask for RTE_FLOW_ITEM_TYPE_PPP. */ +#ifndef __cplusplus +static const struct rte_flow_item_ppp rte_flow_item_ppp_mask = { + .addr = 0xff, + .ctrl = 0xff, + .proto_id = 0xffff, +}; +#endif + /** * Matching pattern item definition. * @@ -2417,6 +2482,23 @@ enum rte_flow_action_type { * See struct rte_flow_action_meter_color. */ RTE_FLOW_ACTION_TYPE_METER_COLOR, + + /** + * Encapsulate flow in L2TPV2 tunnel defined in the + * rte_flow_action_l2tpv2_encap action structure. + * + * See struct rte_flow_action_l2tpv2_encap. + */ + RTE_FLOW_ACTION_TYPE_L2TPV2_ENCAP, + + /** + * Decapsulate outer most L2TPV2 tunnel from matched flow. + * + * If flow pattern does not define a valid L2TPV2 tunnel (as specified + * by RFC2661) then the PMD should return a RTE_FLOW_ERROR_TYPE_ACTION + * error. + */ + RTE_FLOW_ACTION_TYPE_L2TPV2_DECAP, }; /** @@ -3162,6 +3244,41 @@ struct rte_flow_action_meter_color { enum rte_color color; /**< Packet color. */ }; +/** + * @warning + * @b EXPERIMENTAL: this structure may change without prior notice + * + * RTE_FLOW_ACTION_TYPE_L2TPV2_ENCAP + * + * L2TPV2 tunnel end-point encapsulation data definition + * + * The tunnel definition is provided through the flow item pattern the + * provided pattern must conform with RFC7637. The flow definition must be + * provided in order from the RTE_FLOW_ITEM_TYPE_ETH definition up the end item + * which is specified by RTE_FLOW_ITEM_TYPE_END. + * + * The mask field allows user to specify which fields in the flow item + * definitions can be ignored and which have valid data and can be used + * verbatim. + * + * Note: the last field is not used in the definition of a tunnel and can be + * ignored. + * + * Valid flow definition for RTE_FLOW_ACTION_TYPE_L2TPV2_ENCAP include: + * + * - ETH / IPV4 / UDP / L2TPV2 / END + * - ETH / IPV6 / UDP / L2TPV2 / END + * - ETH / VLAN / IPV4 / UDP / L2TPV2 / END + * + */ +struct rte_flow_action_l2tpv2_encap { + /** + * Encapsulating l2tpv2 tunnel definition + * (terminated by the END pattern item). + */ + struct rte_flow_item *definition; +}; + /** * Field IDs for MODIFY_FIELD action. */ diff --git a/lib/net/rte_l2tpv2.h b/lib/net/rte_l2tpv2.h new file mode 100644 index 0000000000..aea3c689be --- /dev/null +++ b/lib/net/rte_l2tpv2.h @@ -0,0 +1,214 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2021 Mellanox Technologies, Ltd + */ + +#ifndef _RTE_L2TPV2_H_ +#define _RTE_L2TPV2_H_ + +/** + * @file + * + * L2TP header: + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |T|L|x|x|S|x|O|P|x|x|x|x| Ver | Length (opt) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Tunnel ID | Session ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ns (opt) | Nr (opt) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Offset Size (opt) | Offset pad... (opt) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * The Type (T) bit indicates the type of message. It is set to 0 for a data + * message and 1 for a control message. + * + * If the Length (L) bit is 1, the Length field is present. This bit MUST be + * set to 1 for control messages. + * + * The x bits are reserved for future extensions. All reserved bits MUST + * be set to 0 on outgoing messages and ignored on incoming messages. + * + * If the Sequence (S) bit is set to 1 the Ns and Nr fields are present. + * The S bit MUST be set to 1 for control messages. + * + * If the Offset (O) bit is 1, the Offset Size field is present. The O + * bit MUST be set to 0 for control messages. + * + * If the Priority (P) bit is 1, this data message should receive + * preferential treatment in its local queuing and transmission. + * The P bit MUST be set to 0 for control messages. + * + * Ver MUST be 2, indicating the version of the L2TP data message header. + * + * The Length field indicates the total length of the message in octets. + * + * Tunnel ID indicates the identifier for the control connection. + * + * Session ID indicates the identifier for a session within a tunnel. + * + * Ns indicates the sequence number for this data or control message. + * + * Nr indicates the sequence number expected in the next control message + * to be received. + * + * The Offset Size field, if present, specifies the number of octets + * past the L2TP header at which the payload data is expected to start. + * Actual data within the offset padding is undefined. If the offset + * field is present, the L2TP header ends after the last octet of the + * offset padding. + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * L2TPv2 Common Header + */ +RTE_STD_C11 +struct rte_l2tpv2_common_hdr { + union { + rte_be16_t flags_version; + struct { +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + rte_be16_t t:1; /**< message Type */ + rte_be16_t l:1; /**< length option bit*/ + rte_be16_t res1:2; /**< reserved */ + rte_be16_t s:1; /**< ns/nr option bit*/ + rte_be16_t res2:1; /**< reserved */ + rte_be16_t o:1; /**< offset option bit*/ + rte_be16_t p:1; /**< priority option bit*/ + rte_be16_t res3:4; /**< reserved */ + rte_be16_t ver:4; /**< protocol version */ +#elif RTE_BYTE_ORDER == RTE_BIG_ENDIAN + rte_be16_t ver:4; /**< protocol version */ + rte_be16_t res3:4; /**< reserved */ + rte_be16_t p:1; /**< priority option bit*/ + rte_be16_t o:1; /**< offset option bit*/ + rte_be16_t res2:1; /**< reserved */ + rte_be16_t s:1; /**< ns/nr option bit*/ + rte_be16_t res1:2; /**< reserved */ + rte_be16_t l:1; /**< length option bit*/ + rte_be16_t t:1; /**< message Type */ +#endif + }; + }; +}; + +/* + * L2TPv2 message Header contains all options(length, ns, nr, + * offset size, offset padding). + */ +struct rte_l2tpv2_msg_with_all_options { + rte_be16_t length; /**< length(16) */ + rte_be16_t tunnel_id; /**< tunnel id(16) */ + rte_be16_t session_id; /**< session id(16) */ + rte_be16_t ns; /**< Ns(16) */ + rte_be16_t nr; /**< Nr(16) */ + rte_be16_t offset_size; /**< offset size(16) */ + uint8_t *offset_padding; /**< offset padding(variable length) */ +}; + +/* + * L2TPv2 message Header contains all options except length(ns, nr, + * offset size, offset padding). + */ +struct rte_l2tpv2_msg_without_length { + rte_be16_t tunnel_id; /**< tunnel id(16) */ + rte_be16_t session_id; /**< session id(16) */ + rte_be16_t ns; /**< Ns(16) */ + rte_be16_t nr; /**< Nr(16) */ + rte_be16_t offset_size; /**< offset size(16) */ + uint8_t *offset_padding; /**< offset padding(variable length) */ +}; + +/* + * L2TPv2 message Header contains all options except ns_nr(length, + * offset size, offset padding). + * Ns and Nr MUST be toghter. + */ +struct rte_l2tpv2_msg_without_ns_nr { + rte_be16_t length; /**< length(16) */ + rte_be16_t tunnel_id; /**< tunnel id(16) */ + rte_be16_t session_id; /**< session id(16) */ + rte_be16_t offset_size; /**< offset size(16) */ + uint8_t *offset_padding; /**< offset padding(variable length) */ +}; + +/* + * L2TPv2 message Header contains all options except ns_nr(length, ns, nr). + * offset size and offset padding MUST be toghter. + */ +struct rte_l2tpv2_msg_without_offset { + rte_be16_t length; /**< length(16) */ + rte_be16_t tunnel_id; /**< tunnel id(16) */ + rte_be16_t session_id; /**< session id(16) */ + rte_be16_t ns; /**< Ns(16) */ + rte_be16_t nr; /**< Nr(16) */ +}; + +/* + * L2TPv2 message Header contains options offset size and offset padding. + */ +struct rte_l2tpv2_msg_with_offset { + rte_be16_t tunnel_id; /**< tunnel id(16) */ + rte_be16_t session_id; /**< session id(16) */ + rte_be16_t offset_size; /**< offset size(16) */ + uint8_t *offset_padding; /**< offset padding(variable length) */ +}; + +/* + * L2TPv2 message Header contains options ns and nr. + */ +struct rte_l2tpv2_msg_with_ns_nr { + rte_be16_t tunnel_id; /**< tunnel id(16) */ + rte_be16_t session_id; /**< session id(16) */ + rte_be16_t ns; /**< Ns(16) */ + rte_be16_t nr; /**< Nr(16) */ +}; + +/* + * L2TPv2 message Header contains option length. + */ +struct rte_l2tpv2_msg_with_length { + rte_be16_t length; /**< length(16) */ + rte_be16_t tunnel_id; /**< tunnel id(16) */ + rte_be16_t session_id; /**< session id(16) */ +}; + +/* + * L2TPv2 message Header without all options. + */ +struct rte_l2tpv2_msg_without_all_options { + rte_be16_t tunnel_id; /**< tunnel id(16) */ + rte_be16_t session_id; /**< session id(16) */ +}; + +/** + * L2TPv2 Combined Message Header Format: Common Header + Options + */ +RTE_STD_C11 +struct rte_l2tpv2_combined_msg_hdr { + struct rte_l2tpv2_common_hdr common; + union { + struct rte_l2tpv2_msg_with_all_options type0; + struct rte_l2tpv2_msg_without_length type1; + struct rte_l2tpv2_msg_without_ns_nr type2; + struct rte_l2tpv2_msg_without_offset type3; + struct rte_l2tpv2_msg_with_offset type4; + struct rte_l2tpv2_msg_with_ns_nr type5; + struct rte_l2tpv2_msg_with_length type6; + struct rte_l2tpv2_msg_without_all_options type7; + }; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_L2TPV2_H_ */ From patchwork Fri Oct 15 09:58:22 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jie Wang X-Patchwork-Id: 101753 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0E3C2A0C4B; Fri, 15 Oct 2021 11:59:03 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id A4C42411FC; Fri, 15 Oct 2021 11:58:56 +0200 (CEST) Received: from mga12.intel.com (mga12.intel.com [192.55.52.136]) by mails.dpdk.org (Postfix) with ESMTP id C823C41203 for ; Fri, 15 Oct 2021 11:58:54 +0200 (CEST) X-IronPort-AV: E=McAfee;i="6200,9189,10137"; a="208000584" X-IronPort-AV: E=Sophos;i="5.85,375,1624345200"; d="scan'208";a="208000584" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by fmsmga106.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Oct 2021 02:58:54 -0700 X-IronPort-AV: E=Sophos;i="5.85,375,1624345200"; d="scan'208";a="492394830" Received: from dpdk.cd.intel.com ([10.240.178.133]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Oct 2021 02:58:50 -0700 From: Jie Wang To: dev@dpdk.org Cc: orika@nvidia.com, ferruh.yigit@intel.com, thomas@monjalon.net, andrew.rybchenko@oktetlabs.ru, xiaoyun.li@intel.com, stevex.yang@intel.com, jingjing.wu@intel.com, beilei.xing@intel.com, wenjun1.wu@intel.com, Jie Wang Date: Fri, 15 Oct 2021 17:58:22 +0800 Message-Id: <20211015095823.701188-3-jie1x.wang@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211015095823.701188-1-jie1x.wang@intel.com> References: <20211012102508.275790-1-jie1x.wang@intel.com> <20211015095823.701188-1-jie1x.wang@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v3 2/3] net/iavf: support PPPoL2TPv2oUDP RSS Hash X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add support for PPP over L2TPv2 over UDP protocol RSS Hash based on inner IP src/dst address and TCP/UDP src/dst port. Patterns are listed below: eth/ipv4(6)/udp/l2tpv2/ppp/ipv4(6) eth/ipv4(6)/udp/l2tpv2/ppp/ipv4(6)/udp eth/ipv4(6)/udp/l2tpv2/ppp/ipv4(6)/tcp Signed-off-by: Wenjun Wu Signed-off-by: Jie Wang --- drivers/net/iavf/iavf_generic_flow.c | 131 +++++++++++++++++++++++++++ drivers/net/iavf/iavf_generic_flow.h | 15 +++ drivers/net/iavf/iavf_hash.c | 108 +++++++++++++++++++++- 3 files changed, 252 insertions(+), 2 deletions(-) diff --git a/drivers/net/iavf/iavf_generic_flow.c b/drivers/net/iavf/iavf_generic_flow.c index b86d99e57d..364904fa02 100644 --- a/drivers/net/iavf/iavf_generic_flow.c +++ b/drivers/net/iavf/iavf_generic_flow.c @@ -1611,6 +1611,137 @@ enum rte_flow_item_type iavf_pattern_eth_ipv6_gre_ipv6_udp[] = { RTE_FLOW_ITEM_TYPE_END, }; +/* PPPoL2TPv2oUDP */ +enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4[] = { + RTE_FLOW_ITEM_TYPE_ETH, + RTE_FLOW_ITEM_TYPE_IPV4, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_L2TPV2, + RTE_FLOW_ITEM_TYPE_PPP, + RTE_FLOW_ITEM_TYPE_IPV4, + RTE_FLOW_ITEM_TYPE_END, +}; + +enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6[] = { + RTE_FLOW_ITEM_TYPE_ETH, + RTE_FLOW_ITEM_TYPE_IPV4, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_L2TPV2, + RTE_FLOW_ITEM_TYPE_PPP, + RTE_FLOW_ITEM_TYPE_IPV6, + RTE_FLOW_ITEM_TYPE_END, +}; + +enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp[] = { + RTE_FLOW_ITEM_TYPE_ETH, + RTE_FLOW_ITEM_TYPE_IPV4, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_L2TPV2, + RTE_FLOW_ITEM_TYPE_PPP, + RTE_FLOW_ITEM_TYPE_IPV4, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_END, +}; + +enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp[] = { + RTE_FLOW_ITEM_TYPE_ETH, + RTE_FLOW_ITEM_TYPE_IPV4, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_L2TPV2, + RTE_FLOW_ITEM_TYPE_PPP, + RTE_FLOW_ITEM_TYPE_IPV4, + RTE_FLOW_ITEM_TYPE_TCP, + RTE_FLOW_ITEM_TYPE_END, +}; + +enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp[] = { + RTE_FLOW_ITEM_TYPE_ETH, + RTE_FLOW_ITEM_TYPE_IPV4, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_L2TPV2, + RTE_FLOW_ITEM_TYPE_PPP, + RTE_FLOW_ITEM_TYPE_IPV6, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_END, +}; + +enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp[] = { + RTE_FLOW_ITEM_TYPE_ETH, + RTE_FLOW_ITEM_TYPE_IPV4, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_L2TPV2, + RTE_FLOW_ITEM_TYPE_PPP, + RTE_FLOW_ITEM_TYPE_IPV6, + RTE_FLOW_ITEM_TYPE_TCP, + RTE_FLOW_ITEM_TYPE_END, +}; + +enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4[] = { + RTE_FLOW_ITEM_TYPE_ETH, + RTE_FLOW_ITEM_TYPE_IPV6, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_L2TPV2, + RTE_FLOW_ITEM_TYPE_PPP, + RTE_FLOW_ITEM_TYPE_IPV4, + RTE_FLOW_ITEM_TYPE_END, +}; + +enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6[] = { + RTE_FLOW_ITEM_TYPE_ETH, + RTE_FLOW_ITEM_TYPE_IPV6, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_L2TPV2, + RTE_FLOW_ITEM_TYPE_PPP, + RTE_FLOW_ITEM_TYPE_IPV6, + RTE_FLOW_ITEM_TYPE_END, +}; + +enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp[] = { + RTE_FLOW_ITEM_TYPE_ETH, + RTE_FLOW_ITEM_TYPE_IPV6, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_L2TPV2, + RTE_FLOW_ITEM_TYPE_PPP, + RTE_FLOW_ITEM_TYPE_IPV4, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_END, +}; + +enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp[] = { + RTE_FLOW_ITEM_TYPE_ETH, + RTE_FLOW_ITEM_TYPE_IPV6, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_L2TPV2, + RTE_FLOW_ITEM_TYPE_PPP, + RTE_FLOW_ITEM_TYPE_IPV4, + RTE_FLOW_ITEM_TYPE_TCP, + RTE_FLOW_ITEM_TYPE_END, +}; + +enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp[] = { + RTE_FLOW_ITEM_TYPE_ETH, + RTE_FLOW_ITEM_TYPE_IPV6, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_L2TPV2, + RTE_FLOW_ITEM_TYPE_PPP, + RTE_FLOW_ITEM_TYPE_IPV6, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_END, +}; + +enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[] = { + RTE_FLOW_ITEM_TYPE_ETH, + RTE_FLOW_ITEM_TYPE_IPV6, + RTE_FLOW_ITEM_TYPE_UDP, + RTE_FLOW_ITEM_TYPE_L2TPV2, + RTE_FLOW_ITEM_TYPE_PPP, + RTE_FLOW_ITEM_TYPE_IPV6, + RTE_FLOW_ITEM_TYPE_TCP, + RTE_FLOW_ITEM_TYPE_END, +}; + + + typedef struct iavf_flow_engine * (*parse_engine_t)(struct iavf_adapter *ad, struct rte_flow *flow, struct iavf_parser_list *parser_list, diff --git a/drivers/net/iavf/iavf_generic_flow.h b/drivers/net/iavf/iavf_generic_flow.h index 4794d1fb80..f2b54e1944 100644 --- a/drivers/net/iavf/iavf_generic_flow.h +++ b/drivers/net/iavf/iavf_generic_flow.h @@ -410,6 +410,21 @@ extern enum rte_flow_item_type iavf_pattern_eth_ipv6_gre_ipv6_tcp[]; extern enum rte_flow_item_type iavf_pattern_eth_ipv6_gre_ipv4_udp[]; extern enum rte_flow_item_type iavf_pattern_eth_ipv6_gre_ipv6_udp[]; +/* PPPoL2TPv2oUDP */ +extern enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4[]; +extern enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6[]; +extern enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp[]; +extern enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp[]; +extern enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp[]; +extern enum rte_flow_item_type iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp[]; +extern enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4[]; +extern enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6[]; +extern enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp[]; +extern enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp[]; +extern enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp[]; +extern enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[]; + + extern const struct rte_flow_ops iavf_flow_ops; /* pattern structure */ diff --git a/drivers/net/iavf/iavf_hash.c b/drivers/net/iavf/iavf_hash.c index 1f2d3772d1..9e7286861e 100644 --- a/drivers/net/iavf/iavf_hash.c +++ b/drivers/net/iavf/iavf_hash.c @@ -34,6 +34,8 @@ /* the second IP header of GTPoGRE */ #define IAVF_PHINT_MID_IPV4 BIT_ULL(7) #define IAVF_PHINT_MID_IPV6 BIT_ULL(8) +/* L2TPV2 */ +#define IAVF_PHINT_L2TPV2 BIT_ULL(9) #define IAVF_PHINT_GTPU_MSK (IAVF_PHINT_GTPU | \ IAVF_PHINT_GTPU_EH | \ @@ -164,6 +166,12 @@ iavf_hash_parse_pattern_action(struct iavf_adapter *ad, VIRTCHNL_PROTO_HDR_ECPRI, \ FIELD_SELECTOR(VIRTCHNL_PROTO_HDR_ECPRI_PC_RTC_ID), {BUFF_NOUSED} } +#define proto_hdr_l2tpv2 { \ + VIRTCHNL_PROTO_HDR_L2TPV2, 0, {BUFF_NOUSED} } + +#define proto_hdr_ppp { \ + VIRTCHNL_PROTO_HDR_PPP, 0, {BUFF_NOUSED} } + #define TUNNEL_LEVEL_OUTER 0 #define TUNNEL_LEVEL_INNER 1 @@ -338,6 +346,52 @@ struct virtchnl_proto_hdrs ipv4_ecpri_tmplt = { TUNNEL_LEVEL_OUTER, 3, {proto_hdr_ipv4, proto_hdr_udp, proto_hdr_ecpri} }; +struct virtchnl_proto_hdrs udp_l2tpv2_ppp_ipv4_tmplt = { + TUNNEL_LEVEL_INNER, 3, + {proto_hdr_l2tpv2, + proto_hdr_ppp, + proto_hdr_ipv4} +}; + +struct virtchnl_proto_hdrs udp_l2tpv2_ppp_ipv6_tmplt = { + TUNNEL_LEVEL_INNER, 3, + {proto_hdr_l2tpv2, + proto_hdr_ppp, + proto_hdr_ipv6} +}; + +struct virtchnl_proto_hdrs udp_l2tpv2_ppp_ipv4_udp_tmplt = { + TUNNEL_LEVEL_INNER, 4, + {proto_hdr_l2tpv2, + proto_hdr_ppp, + proto_hdr_ipv4_with_prot, + proto_hdr_udp} +}; + +struct virtchnl_proto_hdrs udp_l2tpv2_ppp_ipv4_tcp_tmplt = { + TUNNEL_LEVEL_INNER, 4, + {proto_hdr_l2tpv2, + proto_hdr_ppp, + proto_hdr_ipv4_with_prot, + proto_hdr_tcp} +}; + +struct virtchnl_proto_hdrs udp_l2tpv2_ppp_ipv6_udp_tmplt = { + TUNNEL_LEVEL_INNER, 4, + {proto_hdr_l2tpv2, + proto_hdr_ppp, + proto_hdr_ipv6_with_prot, + proto_hdr_udp} +}; + +struct virtchnl_proto_hdrs udp_l2tpv2_ppp_ipv6_tcp_tmplt = { + TUNNEL_LEVEL_INNER, 4, + {proto_hdr_l2tpv2, + proto_hdr_ppp, + proto_hdr_ipv6_with_prot, + proto_hdr_tcp} +}; + /* rss type super set */ /* IPv4 outer */ @@ -493,6 +547,13 @@ static struct iavf_pattern_match_item iavf_hash_pattern_list[] = { {iavf_pattern_eth_ipv6_gre_ipv4_tcp, IAVF_RSS_TYPE_INNER_IPV4_TCP, &inner_ipv4_tcp_tmplt}, {iavf_pattern_eth_ipv4_gre_ipv4_udp, IAVF_RSS_TYPE_INNER_IPV4_UDP, &inner_ipv4_udp_tmplt}, {iavf_pattern_eth_ipv6_gre_ipv4_udp, IAVF_RSS_TYPE_INNER_IPV4_UDP, &inner_ipv4_udp_tmplt}, + {iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4, IAVF_RSS_TYPE_INNER_IPV4, &udp_l2tpv2_ppp_ipv4_tmplt}, + {iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_udp, IAVF_RSS_TYPE_INNER_IPV4_UDP, &udp_l2tpv2_ppp_ipv4_udp_tmplt}, + {iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv4_tcp, IAVF_RSS_TYPE_INNER_IPV4_TCP, &udp_l2tpv2_ppp_ipv4_tcp_tmplt}, + {iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4, IAVF_RSS_TYPE_INNER_IPV4, &udp_l2tpv2_ppp_ipv4_tmplt}, + {iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_udp, IAVF_RSS_TYPE_INNER_IPV4_UDP, &udp_l2tpv2_ppp_ipv4_udp_tmplt}, + {iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv4_tcp, IAVF_RSS_TYPE_INNER_IPV4_TCP, &udp_l2tpv2_ppp_ipv4_tcp_tmplt}, + /* IPv6 */ {iavf_pattern_eth_ipv6, IAVF_RSS_TYPE_OUTER_IPV6, &outer_ipv6_tmplt}, {iavf_pattern_eth_ipv6_frag_ext, IAVF_RSS_TYPE_OUTER_IPV6_FRAG, &outer_ipv6_frag_tmplt}, @@ -553,6 +614,13 @@ static struct iavf_pattern_match_item iavf_hash_pattern_list[] = { {iavf_pattern_eth_ipv6_gre_ipv6_tcp, IAVF_RSS_TYPE_INNER_IPV6_TCP, &inner_ipv6_tcp_tmplt}, {iavf_pattern_eth_ipv4_gre_ipv6_udp, IAVF_RSS_TYPE_INNER_IPV6_UDP, &inner_ipv6_udp_tmplt}, {iavf_pattern_eth_ipv6_gre_ipv6_udp, IAVF_RSS_TYPE_INNER_IPV6_UDP, &inner_ipv6_udp_tmplt}, + {iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6, IAVF_RSS_TYPE_INNER_IPV6, &udp_l2tpv2_ppp_ipv6_tmplt}, + {iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_udp, IAVF_RSS_TYPE_INNER_IPV6_UDP, &udp_l2tpv2_ppp_ipv6_udp_tmplt}, + {iavf_pattern_eth_ipv4_udp_l2tpv2_ppp_ipv6_tcp, IAVF_RSS_TYPE_INNER_IPV6_TCP, &udp_l2tpv2_ppp_ipv6_tcp_tmplt}, + {iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6, IAVF_RSS_TYPE_INNER_IPV6, &udp_l2tpv2_ppp_ipv6_tmplt}, + {iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_udp, IAVF_RSS_TYPE_INNER_IPV6_UDP, &udp_l2tpv2_ppp_ipv6_udp_tmplt}, + {iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp, IAVF_RSS_TYPE_INNER_IPV6_TCP, &udp_l2tpv2_ppp_ipv6_tcp_tmplt}, + }; static struct iavf_flow_engine iavf_hash_engine = { @@ -687,13 +755,17 @@ iavf_hash_parse_pattern(const struct rte_flow_item pattern[], uint64_t *phint, switch (item->type) { case RTE_FLOW_ITEM_TYPE_IPV4: - if (!(*phint & IAVF_PHINT_GTPU_MSK) && !(*phint & IAVF_PHINT_GRE)) + if (!(*phint & IAVF_PHINT_GTPU_MSK) && + !(*phint & IAVF_PHINT_GRE) && + !(*phint & IAVF_PHINT_L2TPV2)) *phint |= IAVF_PHINT_OUTER_IPV4; if ((*phint & IAVF_PHINT_GRE) && !(*phint & IAVF_PHINT_GTPU_MSK)) *phint |= IAVF_PHINT_MID_IPV4; break; case RTE_FLOW_ITEM_TYPE_IPV6: - if (!(*phint & IAVF_PHINT_GTPU_MSK) && !(*phint & IAVF_PHINT_GRE)) + if (!(*phint & IAVF_PHINT_GTPU_MSK) && + !(*phint & IAVF_PHINT_GRE) && + !(*phint & IAVF_PHINT_L2TPV2)) *phint |= IAVF_PHINT_OUTER_IPV6; if ((*phint & IAVF_PHINT_GRE) && !(*phint & IAVF_PHINT_GTPU_MSK)) *phint |= IAVF_PHINT_MID_IPV6; @@ -728,6 +800,10 @@ iavf_hash_parse_pattern(const struct rte_flow_item pattern[], uint64_t *phint, break; case RTE_FLOW_ITEM_TYPE_GRE: *phint |= IAVF_PHINT_GRE; + break; + case RTE_FLOW_ITEM_TYPE_L2TPV2: + *phint |= IAVF_PHINT_L2TPV2; + break; default: break; } @@ -1050,12 +1126,40 @@ iavf_refine_proto_hdrs_by_pattern(struct virtchnl_proto_hdrs *proto_hdrs, proto_hdrs->tunnel_level = tun_lvl; } +static void +iavf_refine_proto_hdrs_l2tpv2(struct virtchnl_proto_hdrs *proto_hdrs, + uint64_t phint) +{ + struct virtchnl_proto_hdr *hdr1; + int i; + + if (!(phint & IAVF_PHINT_L2TPV2)) + return; + + if (proto_hdrs->tunnel_level == TUNNEL_LEVEL_INNER) { + /* shift headers layer */ + for (i = proto_hdrs->count - 1 + 1; i > 0; i--) + proto_hdrs->proto_hdr[i] = proto_hdrs->proto_hdr[i - 1]; + + /* adding outer ip header at layer 0 */ + hdr1 = &proto_hdrs->proto_hdr[0]; + hdr1->field_selector = 0; + proto_hdrs->count++; + proto_hdrs->tunnel_level = TUNNEL_LEVEL_OUTER; + if (phint & IAVF_PHINT_OUTER_IPV4) + VIRTCHNL_SET_PROTO_HDR_TYPE(hdr1, IPV4); + else if (phint & IAVF_PHINT_OUTER_IPV6) + VIRTCHNL_SET_PROTO_HDR_TYPE(hdr1, IPV6); + } +} + static void iavf_refine_proto_hdrs(struct virtchnl_proto_hdrs *proto_hdrs, uint64_t rss_type, uint64_t phint) { iavf_refine_proto_hdrs_l234(proto_hdrs, rss_type); iavf_refine_proto_hdrs_by_pattern(proto_hdrs, phint); iavf_refine_proto_hdrs_gtpu(proto_hdrs, rss_type); + iavf_refine_proto_hdrs_l2tpv2(proto_hdrs, phint); } static uint64_t invalid_rss_comb[] = { From patchwork Fri Oct 15 09:58:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jie Wang X-Patchwork-Id: 101754 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id F2306A0C4B; Fri, 15 Oct 2021 11:59:09 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 0E0E3411FF; Fri, 15 Oct 2021 11:59:03 +0200 (CEST) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by mails.dpdk.org (Postfix) with ESMTP id 6321D40692 for ; Fri, 15 Oct 2021 11:59:01 +0200 (CEST) X-IronPort-AV: E=McAfee;i="6200,9189,10137"; a="227840739" X-IronPort-AV: E=Sophos;i="5.85,375,1624345200"; d="scan'208";a="227840739" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Oct 2021 02:59:00 -0700 X-IronPort-AV: E=Sophos;i="5.85,375,1624345200"; d="scan'208";a="492394850" Received: from dpdk.cd.intel.com ([10.240.178.133]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Oct 2021 02:58:56 -0700 From: Jie Wang To: dev@dpdk.org Cc: orika@nvidia.com, ferruh.yigit@intel.com, thomas@monjalon.net, andrew.rybchenko@oktetlabs.ru, xiaoyun.li@intel.com, stevex.yang@intel.com, jingjing.wu@intel.com, beilei.xing@intel.com, wenjun1.wu@intel.com, Jie Wang Date: Fri, 15 Oct 2021 17:58:23 +0800 Message-Id: <20211015095823.701188-4-jie1x.wang@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211015095823.701188-1-jie1x.wang@intel.com> References: <20211012102508.275790-1-jie1x.wang@intel.com> <20211015095823.701188-1-jie1x.wang@intel.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v3 3/3] app/testpmd: support L2TPV2 and PPP protocol pattern X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add support for test-pmd to parse protocol pattern L2TPv2 and PPP. Signed-off-by: Wenjun Wu Signed-off-by: Jie Wang --- app/test-pmd/cmdline.c | 244 ++++++++++++++++++++++ app/test-pmd/cmdline_flow.c | 396 ++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.h | 22 ++ 3 files changed, 662 insertions(+) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 36d50fd3c7..bba761ad4b 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -13300,6 +13300,247 @@ cmdline_parse_inst_t cmd_set_nvgre_with_vlan = { }, }; +/** Set L2TPV2 encapsulation details */ +struct cmd_set_l2tpv2_result { + cmdline_fixed_string_t set; + cmdline_fixed_string_t l2tpv2; + cmdline_fixed_string_t pos_token; + cmdline_fixed_string_t ip_version; + uint32_t vlan_present:1; + uint16_t flags_version; + uint16_t session_id; + uint16_t udp_src; + uint16_t udp_dst; + cmdline_ipaddr_t ip_src; + cmdline_ipaddr_t ip_dst; + uint16_t tci; + uint8_t tos; + uint8_t ttl; + struct rte_ether_addr eth_src; + struct rte_ether_addr eth_dst; +}; + +cmdline_parse_token_string_t cmd_set_l2tpv2_set = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, set, "set"); +cmdline_parse_token_string_t cmd_set_l2tpv2_l2tpv2 = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, l2tpv2, "l2tpv2"); +cmdline_parse_token_string_t cmd_set_l2tpv2_l2tpv2_tos_ttl = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, l2tpv2, + "l2tpv2-tos-ttl"); +cmdline_parse_token_string_t cmd_set_l2tpv2_l2tpv2_with_vlan = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, l2tpv2, + "l2tpv2-with-vlan"); +cmdline_parse_token_string_t cmd_set_l2tpv2_ip_version = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token, + "ip-version"); +cmdline_parse_token_string_t cmd_set_l2tpv2_ip_version_value = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, ip_version, + "ipv4#ipv6"); +cmdline_parse_token_string_t cmd_set_l2tpv2_flags_version = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token, + "flags_version"); +cmdline_parse_token_num_t cmd_set_l2tpv2_flags_version_value = + TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, flags_version, + RTE_UINT16); +cmdline_parse_token_string_t cmd_set_l2tpv2_session_id = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token, + "session_id"); +cmdline_parse_token_num_t cmd_set_l2tpv2_session_id_value = + TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, session_id, + RTE_UINT16); +cmdline_parse_token_string_t cmd_set_l2tpv2_udp_src = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token, + "udp-src"); +cmdline_parse_token_num_t cmd_set_l2tpv2_udp_src_value = + TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, udp_src, + RTE_UINT16); +cmdline_parse_token_string_t cmd_set_l2tpv2_udp_dst = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token, + "udp-dst"); +cmdline_parse_token_num_t cmd_set_l2tpv2_udp_dst_value = + TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, udp_dst, + RTE_UINT16); +cmdline_parse_token_string_t cmd_set_l2tpv2_ip_tos = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token, + "ip-tos"); +cmdline_parse_token_num_t cmd_set_l2tpv2_ip_tos_value = + TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, tos, RTE_UINT8); +cmdline_parse_token_string_t cmd_set_l2tpv2_ip_ttl = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token, + "ip-ttl"); +cmdline_parse_token_num_t cmd_set_l2tpv2_ip_ttl_value = + TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, ttl, RTE_UINT8); +cmdline_parse_token_string_t cmd_set_l2tpv2_ip_src = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token, + "ip-src"); +cmdline_parse_token_ipaddr_t cmd_set_l2tpv2_ip_src_value = + TOKEN_IPADDR_INITIALIZER(struct cmd_set_l2tpv2_result, ip_src); +cmdline_parse_token_string_t cmd_set_l2tpv2_ip_dst = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token, + "ip-dst"); +cmdline_parse_token_ipaddr_t cmd_set_l2tpv2_ip_dst_value = + TOKEN_IPADDR_INITIALIZER(struct cmd_set_l2tpv2_result, ip_dst); +cmdline_parse_token_string_t cmd_set_l2tpv2_vlan = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token, + "vlan-tci"); +cmdline_parse_token_num_t cmd_set_l2tpv2_vlan_value = + TOKEN_NUM_INITIALIZER(struct cmd_set_l2tpv2_result, tci, RTE_UINT16); +cmdline_parse_token_string_t cmd_set_l2tpv2_eth_src = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token, + "eth-src"); +cmdline_parse_token_etheraddr_t cmd_set_l2tpv2_eth_src_value = + TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_l2tpv2_result, eth_src); +cmdline_parse_token_string_t cmd_set_l2tpv2_eth_dst = + TOKEN_STRING_INITIALIZER(struct cmd_set_l2tpv2_result, pos_token, + "eth-dst"); +cmdline_parse_token_etheraddr_t cmd_set_l2tpv2_eth_dst_value = + TOKEN_ETHERADDR_INITIALIZER(struct cmd_set_l2tpv2_result, eth_dst); + +static void cmd_set_l2tpv2_parsed(void *parsed_result, + __rte_unused struct cmdline *cl, + __rte_unused void *data) +{ + struct cmd_set_l2tpv2_result *res = parsed_result; + + l2tpv2_encap_conf.select_tos_ttl = 0; + if (strcmp(res->l2tpv2, "l2tpv2") == 0) + l2tpv2_encap_conf.select_vlan = 0; + else if (strcmp(res->l2tpv2, "l2tpv2-with-vlan") == 0) + l2tpv2_encap_conf.select_vlan = 1; + else if (strcmp(res->l2tpv2, "l2tpv2-tos-ttl") == 0) { + l2tpv2_encap_conf.select_vlan = 0; + l2tpv2_encap_conf.select_tos_ttl = 1; + } + if (strcmp(res->ip_version, "ipv4") == 0) + l2tpv2_encap_conf.select_ipv4 = 1; + else if (strcmp(res->ip_version, "ipv6") == 0) + l2tpv2_encap_conf.select_ipv4 = 0; + else + return; + + l2tpv2_encap_conf.flags_version = res->flags_version; + l2tpv2_encap_conf.session_id = res->session_id; + l2tpv2_encap_conf.udp_src = res->udp_src; + l2tpv2_encap_conf.udp_dst = res->udp_dst; + l2tpv2_encap_conf.ip_tos = res->tos; + l2tpv2_encap_conf.ip_ttl = res->ttl; + if (l2tpv2_encap_conf.select_ipv4) { + IPV4_ADDR_TO_UINT(res->ip_src, l2tpv2_encap_conf.ipv4_src); + IPV4_ADDR_TO_UINT(res->ip_dst, l2tpv2_encap_conf.ipv4_dst); + } else { + IPV6_ADDR_TO_ARRAY(res->ip_src, l2tpv2_encap_conf.ipv6_src); + IPV6_ADDR_TO_ARRAY(res->ip_dst, l2tpv2_encap_conf.ipv6_dst); + } + if (l2tpv2_encap_conf.select_vlan) + l2tpv2_encap_conf.vlan_tci = rte_cpu_to_be_16(res->tci); + rte_memcpy(l2tpv2_encap_conf.eth_src, res->eth_src.addr_bytes, + RTE_ETHER_ADDR_LEN); + rte_memcpy(l2tpv2_encap_conf.eth_dst, res->eth_dst.addr_bytes, + RTE_ETHER_ADDR_LEN); +} + +cmdline_parse_inst_t cmd_set_l2tpv2 = { + .f = cmd_set_l2tpv2_parsed, + .data = NULL, + .help_str = "set l2tpv2 ip-version ipv4|ipv6 flags_version" + " session_id udp-src " + " udp-dst ip-src ip-dst eth-src" + " eth-dst ", + .tokens = { + (void *)&cmd_set_l2tpv2_set, + (void *)&cmd_set_l2tpv2_l2tpv2, + (void *)&cmd_set_l2tpv2_ip_version, + (void *)&cmd_set_l2tpv2_ip_version_value, + (void *)&cmd_set_l2tpv2_flags_version, + (void *)&cmd_set_l2tpv2_flags_version_value, + (void *)&cmd_set_l2tpv2_session_id, + (void *)&cmd_set_l2tpv2_session_id_value, + (void *)&cmd_set_l2tpv2_udp_src, + (void *)&cmd_set_l2tpv2_udp_src_value, + (void *)&cmd_set_l2tpv2_udp_dst, + (void *)&cmd_set_l2tpv2_udp_dst_value, + (void *)&cmd_set_l2tpv2_ip_src, + (void *)&cmd_set_l2tpv2_ip_src_value, + (void *)&cmd_set_l2tpv2_ip_dst, + (void *)&cmd_set_l2tpv2_ip_dst_value, + (void *)&cmd_set_l2tpv2_eth_src, + (void *)&cmd_set_l2tpv2_eth_src_value, + (void *)&cmd_set_l2tpv2_eth_dst, + (void *)&cmd_set_l2tpv2_eth_dst_value, + NULL, + }, +}; + +cmdline_parse_inst_t cmd_set_l2tpv2_tos_ttl = { + .f = cmd_set_l2tpv2_parsed, + .data = NULL, + .help_str = "set l2tpv2-tos-ttl ip-version ipv4|ipv6 flags_version" + " session_id udp-src " + " udp-dst ip-tos ip-ttl ip-src" + " ip-dst eth-src eth-dst ", + .tokens = { + (void *)&cmd_set_l2tpv2_set, + (void *)&cmd_set_l2tpv2_l2tpv2_tos_ttl, + (void *)&cmd_set_l2tpv2_ip_version, + (void *)&cmd_set_l2tpv2_ip_version_value, + (void *)&cmd_set_l2tpv2_flags_version, + (void *)&cmd_set_l2tpv2_flags_version_value, + (void *)&cmd_set_l2tpv2_session_id, + (void *)&cmd_set_l2tpv2_session_id_value, + (void *)&cmd_set_l2tpv2_udp_src, + (void *)&cmd_set_l2tpv2_udp_src_value, + (void *)&cmd_set_l2tpv2_udp_dst, + (void *)&cmd_set_l2tpv2_udp_dst_value, + (void *)&cmd_set_l2tpv2_ip_tos, + (void *)&cmd_set_l2tpv2_ip_tos_value, + (void *)&cmd_set_l2tpv2_ip_ttl, + (void *)&cmd_set_l2tpv2_ip_ttl_value, + (void *)&cmd_set_l2tpv2_ip_src, + (void *)&cmd_set_l2tpv2_ip_src_value, + (void *)&cmd_set_l2tpv2_ip_dst, + (void *)&cmd_set_l2tpv2_ip_dst_value, + (void *)&cmd_set_l2tpv2_eth_src, + (void *)&cmd_set_l2tpv2_eth_src_value, + (void *)&cmd_set_l2tpv2_eth_dst, + (void *)&cmd_set_l2tpv2_eth_dst_value, + NULL, + }, +}; + +cmdline_parse_inst_t cmd_set_l2tpv2_with_vlan = { + .f = cmd_set_l2tpv2_parsed, + .data = NULL, + .help_str = "set l2tpv2-with-vlan ip-version ipv4|ipv6 flags_version" + " session_id udp-src " + " udp-dst ip-src ip-dst vlan-tci" + " eth-src eth-dst ", + .tokens = { + (void *)&cmd_set_l2tpv2_set, + (void *)&cmd_set_l2tpv2_l2tpv2_with_vlan, + (void *)&cmd_set_l2tpv2_ip_version, + (void *)&cmd_set_l2tpv2_ip_version_value, + (void *)&cmd_set_l2tpv2_flags_version, + (void *)&cmd_set_l2tpv2_flags_version_value, + (void *)&cmd_set_l2tpv2_session_id, + (void *)&cmd_set_l2tpv2_session_id_value, + (void *)&cmd_set_l2tpv2_udp_src, + (void *)&cmd_set_l2tpv2_udp_src_value, + (void *)&cmd_set_l2tpv2_udp_dst, + (void *)&cmd_set_l2tpv2_udp_dst_value, + (void *)&cmd_set_l2tpv2_ip_src, + (void *)&cmd_set_l2tpv2_ip_src_value, + (void *)&cmd_set_l2tpv2_ip_dst, + (void *)&cmd_set_l2tpv2_ip_dst_value, + (void *)&cmd_set_l2tpv2_vlan, + (void *)&cmd_set_l2tpv2_vlan_value, + (void *)&cmd_set_l2tpv2_eth_src, + (void *)&cmd_set_l2tpv2_eth_src_value, + (void *)&cmd_set_l2tpv2_eth_dst, + (void *)&cmd_set_l2tpv2_eth_dst_value, + NULL, + }, +}; + /** Set L2 encapsulation details */ struct cmd_set_l2_encap_result { cmdline_fixed_string_t set; @@ -17774,6 +18015,9 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_vxlan_with_vlan, (cmdline_parse_inst_t *)&cmd_set_nvgre, (cmdline_parse_inst_t *)&cmd_set_nvgre_with_vlan, + (cmdline_parse_inst_t *)&cmd_set_l2tpv2, + (cmdline_parse_inst_t *)&cmd_set_l2tpv2_tos_ttl, + (cmdline_parse_inst_t *)&cmd_set_l2tpv2_with_vlan, (cmdline_parse_inst_t *)&cmd_set_l2_encap, (cmdline_parse_inst_t *)&cmd_set_l2_encap_with_vlan, (cmdline_parse_inst_t *)&cmd_set_l2_decap, diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 0b5856c7d5..4f73d4f39d 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -306,6 +306,23 @@ enum index { ITEM_POL_PORT, ITEM_POL_METER, ITEM_POL_POLICY, + ITEM_L2TPV2, + ITEM_L2TPV2_COMMON, + ITEM_L2TPV2_COMMON_TYPE, + ITEM_L2TPV2_COMMON_TYPE_DATA_L, + ITEM_L2TPV2_COMMON_TYPE_CTRL, + ITEM_L2TPV2_MSG_DATA_L_LENGTH, + ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID, + ITEM_L2TPV2_MSG_DATA_L_SESSION_ID, + ITEM_L2TPV2_MSG_CTRL_LENGTH, + ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID, + ITEM_L2TPV2_MSG_CTRL_SESSION_ID, + ITEM_L2TPV2_MSG_CTRL_NS, + ITEM_L2TPV2_MSG_CTRL_NR, + ITEM_PPP, + ITEM_PPP_ADDR, + ITEM_PPP_CTRL, + ITEM_PPP_PROTO_ID, /* Validate/create actions. */ ACTIONS, @@ -376,6 +393,8 @@ enum index { ACTION_VXLAN_DECAP, ACTION_NVGRE_ENCAP, ACTION_NVGRE_DECAP, + ACTION_L2TPV2_ENCAP, + ACTION_L2TPV2_DECAP, ACTION_L2_ENCAP, ACTION_L2_DECAP, ACTION_MPLSOGRE_ENCAP, @@ -581,6 +600,44 @@ struct action_nvgre_encap_data { struct rte_flow_item_nvgre item_nvgre; }; +struct l2tpv2_encap_conf l2tpv2_encap_conf = { + .select_ipv4 = 1, + .select_vlan = 0, + .select_tos_ttl = 0, + .flags_version = 0, + .session_id = 0, + .udp_src = 0, + .udp_dst = 1701, + .ipv4_src = RTE_IPV4(127, 0, 0, 1), + .ipv4_dst = RTE_IPV4(255, 255, 255, 255), + .ipv6_src = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x01", + .ipv6_dst = "\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x11\x11", + .vlan_tci = 0, + .ip_tos = 0, + .ip_ttl = 255, + .eth_src = "\x00\x00\x00\x00\x00\x00", + .eth_dst = "\xff\xff\xff\xff\xff\xff", +}; + +/** Maximum number of items in struct rte_flow_action_l2tpv2_encap. */ +#define ACTION_L2TPV2_ENCAP_ITEMS_NUM 6 + +/** Storage for struct rte_flow_action_l2tpv2_encap including external data. */ +struct action_l2tpv2_encap_data { + struct rte_flow_action_l2tpv2_encap conf; + struct rte_flow_item items[ACTION_L2TPV2_ENCAP_ITEMS_NUM]; + struct rte_flow_item_eth item_eth; + struct rte_flow_item_vlan item_vlan; + union { + struct rte_flow_item_ipv4 item_ipv4; + struct rte_flow_item_ipv6 item_ipv6; + }; + struct rte_flow_item_udp item_udp; + struct rte_flow_item_l2tpv2 item_l2tpv2; +}; + struct l2_encap_conf l2_encap_conf; struct l2_decap_conf l2_decap_conf; @@ -614,6 +671,7 @@ struct rte_flow_action_port_id sample_port_id[RAW_SAMPLE_CONFS_MAX_NUM]; struct rte_flow_action_raw_encap sample_encap[RAW_SAMPLE_CONFS_MAX_NUM]; struct action_vxlan_encap_data sample_vxlan_encap[RAW_SAMPLE_CONFS_MAX_NUM]; struct action_nvgre_encap_data sample_nvgre_encap[RAW_SAMPLE_CONFS_MAX_NUM]; +struct action_l2tpv2_encap_data sample_l2tpv2_encap[RAW_SAMPLE_CONFS_MAX_NUM]; struct action_rss_data sample_rss_data[RAW_SAMPLE_CONFS_MAX_NUM]; struct rte_flow_action_vf sample_vf[RAW_SAMPLE_CONFS_MAX_NUM]; @@ -999,6 +1057,8 @@ static const enum index next_item[] = { ITEM_GENEVE_OPT, ITEM_INTEGRITY, ITEM_CONNTRACK, + ITEM_L2TPV2, + ITEM_PPP, END_SET, ZERO, }; @@ -1367,6 +1427,31 @@ static const enum index item_integrity_lv[] = { ZERO, }; +static const enum index item_l2tpv2[] = { + ITEM_L2TPV2_COMMON, + ITEM_NEXT, + ZERO, +}; + +static const enum index item_l2tpv2_common[] = { + ITEM_L2TPV2_COMMON_TYPE, + ZERO, +}; + +static const enum index item_l2tpv2_common_type[] = { + ITEM_L2TPV2_COMMON_TYPE_DATA_L, + ITEM_L2TPV2_COMMON_TYPE_CTRL, + ZERO, +}; + +static const enum index item_ppp[] = { + ITEM_PPP_ADDR, + ITEM_PPP_CTRL, + ITEM_PPP_PROTO_ID, + ITEM_NEXT, + ZERO, +}; + static const enum index next_action[] = { ACTION_END, ACTION_VOID, @@ -1400,6 +1485,8 @@ static const enum index next_action[] = { ACTION_VXLAN_DECAP, ACTION_NVGRE_ENCAP, ACTION_NVGRE_DECAP, + ACTION_L2TPV2_ENCAP, + ACTION_L2TPV2_DECAP, ACTION_L2_ENCAP, ACTION_L2_DECAP, ACTION_MPLSOGRE_ENCAP, @@ -1687,6 +1774,7 @@ static const enum index next_action_sample[] = { ACTION_RAW_ENCAP, ACTION_VXLAN_ENCAP, ACTION_NVGRE_ENCAP, + ACTION_L2TPV2_ENCAP, ACTION_NEXT, ZERO, }; @@ -1757,6 +1845,9 @@ static int parse_vc_action_vxlan_encap(struct context *, const struct token *, static int parse_vc_action_nvgre_encap(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_vc_action_l2tpv2_encap(struct context *, const struct token *, + const char *, unsigned int, void *, + unsigned int); static int parse_vc_action_l2_encap(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -3606,6 +3697,136 @@ static const struct token token_list[] = { item_param), .args = ARGS(ARGS_ENTRY(struct rte_flow_item_conntrack, flags)), }, + [ITEM_L2TPV2] = { + .name = "l2tpv2", + .help = "match l2tpv2 header", + .priv = PRIV_ITEM(L2TPV2, sizeof(struct rte_flow_item_l2tpv2)), + .next = NEXT(item_l2tpv2), + .call = parse_vc, + }, + [ITEM_L2TPV2_COMMON] = { + .name = "common", + .help = "l2tpv2 common header", + .next = NEXT(item_l2tpv2_common), + }, + [ITEM_L2TPV2_COMMON_TYPE] = { + .name = "type", + .help = "type of common header", + .next = NEXT(item_l2tpv2_common_type), + .args = ARGS(ARG_ENTRY_HTON(struct rte_flow_item_l2tpv2)), + }, + [ITEM_L2TPV2_COMMON_TYPE_DATA_L] = { + .name = "data_l", + .help = "Type #6: data message with length option", + .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_DATA_L_LENGTH, + ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID, + ITEM_L2TPV2_MSG_DATA_L_SESSION_ID, + ITEM_NEXT)), + .call = parse_vc, + }, + [ITEM_L2TPV2_MSG_DATA_L_LENGTH] = { + .name = "length", + .help = "message length", + .next = NEXT(item_l2tpv2, NEXT_ENTRY(COMMON_UNSIGNED), + item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, + hdr.type7.tunnel_id)), + }, + [ITEM_L2TPV2_MSG_DATA_L_TUNNEL_ID] = { + .name = "tunnel_id", + .help = "tunnel identifier", + .next = NEXT(item_l2tpv2, NEXT_ENTRY(COMMON_UNSIGNED), + item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, + hdr.type7.tunnel_id)), + }, + [ITEM_L2TPV2_MSG_DATA_L_SESSION_ID] = { + .name = "session_id", + .help = "session identifier", + .next = NEXT(item_l2tpv2, NEXT_ENTRY(COMMON_UNSIGNED), + item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, + hdr.type7.session_id)), + }, + [ITEM_L2TPV2_COMMON_TYPE_CTRL] = { + .name = "control", + .help = "Type #3: conrtol message contains length, ns, nr options", + .next = NEXT(NEXT_ENTRY(ITEM_L2TPV2_MSG_CTRL_LENGTH, + ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID, + ITEM_L2TPV2_MSG_CTRL_SESSION_ID, + ITEM_L2TPV2_MSG_CTRL_NS, + ITEM_L2TPV2_MSG_CTRL_NR, + ITEM_NEXT)), + .call = parse_vc, + }, + [ITEM_L2TPV2_MSG_CTRL_LENGTH] = { + .name = "length", + .help = "message length", + .next = NEXT(item_l2tpv2, NEXT_ENTRY(COMMON_UNSIGNED), + item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, + hdr.type3.length)), + }, + [ITEM_L2TPV2_MSG_CTRL_TUNNEL_ID] = { + .name = "tunnel_id", + .help = "tunnel identifier", + .next = NEXT(item_l2tpv2, NEXT_ENTRY(COMMON_UNSIGNED), + item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, + hdr.type3.tunnel_id)), + }, + [ITEM_L2TPV2_MSG_CTRL_SESSION_ID] = { + .name = "session_id", + .help = "session identifier", + .next = NEXT(item_l2tpv2, NEXT_ENTRY(COMMON_UNSIGNED), + item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, + hdr.type3.session_id)), + }, + [ITEM_L2TPV2_MSG_CTRL_NS] = { + .name = "ns", + .help = "sequence number for message", + .next = NEXT(item_l2tpv2, NEXT_ENTRY(COMMON_UNSIGNED), + item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, + hdr.type3.ns)), + }, + [ITEM_L2TPV2_MSG_CTRL_NR] = { + .name = "nr", + .help = "sequence number for next receive message", + .next = NEXT(item_l2tpv2, NEXT_ENTRY(COMMON_UNSIGNED), + item_param), + .args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_l2tpv2, + hdr.type3.nr)), + }, + [ITEM_PPP] = { + .name = "ppp", + .help = "match ppp header", + .priv = PRIV_ITEM(PPP, sizeof(struct rte_flow_item_ppp)), + .next = NEXT(item_ppp), + .call = parse_vc, + }, + [ITEM_PPP_ADDR] = { + .name = "addr", + .help = "ppp address", + .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED), + item_param), + .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, addr)), + }, + [ITEM_PPP_CTRL] = { + .name = "ctrl", + .help = "ppp control", + .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED), + item_param), + .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, ctrl)), + }, + [ITEM_PPP_PROTO_ID] = { + .name = "proto_id", + .help = "ppp protocol id", + .next = NEXT(item_ppp, NEXT_ENTRY(COMMON_UNSIGNED), + item_param), + .args = ARGS(ARGS_ENTRY(struct rte_flow_item_ppp, proto_id)), + }, /* Validate/create actions. */ [ACTIONS] = { .name = "actions", @@ -4125,6 +4346,24 @@ static const struct token token_list[] = { .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), .call = parse_vc, }, + [ACTION_L2TPV2_ENCAP] = { + .name = "l2tpv2_encap", + .help = "L2TPV2 encapsulation, uses configuration set by \"set" + " l2tpv2\"", + .priv = PRIV_ACTION(L2TPV2_ENCAP, + sizeof(struct action_l2tpv2_encap_data)), + .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), + .call = parse_vc_action_l2tpv2_encap, + }, + [ACTION_L2TPV2_DECAP] = { + .name = "l2tpv2_decap", + .help = "Performs a decapsulation action by stripping all" + " headers of the L2TPV2 tunnel network overlay from the" + " matched flow.", + .priv = PRIV_ACTION(L2TPV2_DECAP, 0), + .next = NEXT(NEXT_ENTRY(ACTION_NEXT)), + .call = parse_vc, + }, [ACTION_L2_ENCAP] = { .name = "l2_encap", .help = "l2 encap, uses configuration set by" @@ -5907,6 +6146,152 @@ parse_vc_action_nvgre_encap(struct context *ctx, const struct token *token, return ret; } +/** Setup L2TPV2 encap configuration. */ +static int +parse_setup_l2tpv2_encap_data(struct action_l2tpv2_encap_data *action_l2tpv2_encap_data) +{ + /* Set up default configuration. */ + *action_l2tpv2_encap_data = (struct action_l2tpv2_encap_data){ + .conf = (struct rte_flow_action_l2tpv2_encap){ + .definition = action_l2tpv2_encap_data->items, + }, + .items = { + { + .type = RTE_FLOW_ITEM_TYPE_ETH, + .spec = &action_l2tpv2_encap_data->item_eth, + .mask = &rte_flow_item_eth_mask, + }, + { + .type = RTE_FLOW_ITEM_TYPE_VLAN, + .spec = &action_l2tpv2_encap_data->item_vlan, + .mask = &rte_flow_item_vlan_mask, + }, + { + .type = RTE_FLOW_ITEM_TYPE_IPV4, + .spec = &action_l2tpv2_encap_data->item_ipv4, + .mask = &rte_flow_item_ipv4_mask, + }, + { + .type = RTE_FLOW_ITEM_TYPE_UDP, + .spec = &action_l2tpv2_encap_data->item_udp, + .mask = &rte_flow_item_udp_mask, + }, + { + .type = RTE_FLOW_ITEM_TYPE_L2TPV2, + .spec = &action_l2tpv2_encap_data->item_l2tpv2, + .mask = &rte_flow_item_l2tpv2_mask, + }, + { + .type = RTE_FLOW_ITEM_TYPE_END, + }, + }, + .item_eth.type = 0, + .item_vlan = { + .tci = l2tpv2_encap_conf.vlan_tci, + .inner_type = 0, + }, + .item_ipv4.hdr = { + .src_addr = l2tpv2_encap_conf.ipv4_src, + .dst_addr = l2tpv2_encap_conf.ipv4_dst, + }, + .item_udp.hdr = { + .src_port = l2tpv2_encap_conf.udp_src, + .dst_port = l2tpv2_encap_conf.udp_dst, + }, + }; + memcpy(action_l2tpv2_encap_data->item_eth.dst.addr_bytes, + l2tpv2_encap_conf.eth_dst, RTE_ETHER_ADDR_LEN); + memcpy(action_l2tpv2_encap_data->item_eth.src.addr_bytes, + l2tpv2_encap_conf.eth_src, RTE_ETHER_ADDR_LEN); + if (!l2tpv2_encap_conf.select_ipv4) { + memcpy(&action_l2tpv2_encap_data->item_ipv6.hdr.src_addr, + &l2tpv2_encap_conf.ipv6_src, + sizeof(l2tpv2_encap_conf.ipv6_src)); + memcpy(&action_l2tpv2_encap_data->item_ipv6.hdr.dst_addr, + &l2tpv2_encap_conf.ipv6_dst, + sizeof(l2tpv2_encap_conf.ipv6_dst)); + action_l2tpv2_encap_data->items[2] = (struct rte_flow_item){ + .type = RTE_FLOW_ITEM_TYPE_IPV6, + .spec = &action_l2tpv2_encap_data->item_ipv6, + .mask = &rte_flow_item_ipv6_mask, + }; + } + if (!l2tpv2_encap_conf.select_vlan) + action_l2tpv2_encap_data->items[1].type = + RTE_FLOW_ITEM_TYPE_VOID; + if (l2tpv2_encap_conf.select_tos_ttl) { + if (l2tpv2_encap_conf.select_ipv4) { + static struct rte_flow_item_ipv4 ipv4_mask_tos; + + memcpy(&ipv4_mask_tos, &rte_flow_item_ipv4_mask, + sizeof(ipv4_mask_tos)); + ipv4_mask_tos.hdr.type_of_service = 0xff; + ipv4_mask_tos.hdr.time_to_live = 0xff; + action_l2tpv2_encap_data->item_ipv4.hdr.type_of_service = + l2tpv2_encap_conf.ip_tos; + action_l2tpv2_encap_data->item_ipv4.hdr.time_to_live = + l2tpv2_encap_conf.ip_ttl; + action_l2tpv2_encap_data->items[2].mask = + &ipv4_mask_tos; + } else { + static struct rte_flow_item_ipv6 ipv6_mask_tos; + + memcpy(&ipv6_mask_tos, &rte_flow_item_ipv6_mask, + sizeof(ipv6_mask_tos)); + ipv6_mask_tos.hdr.vtc_flow |= + RTE_BE32(0xfful << RTE_IPV6_HDR_TC_SHIFT); + ipv6_mask_tos.hdr.hop_limits = 0xff; + action_l2tpv2_encap_data->item_ipv6.hdr.vtc_flow |= + rte_cpu_to_be_32 + ((uint32_t)l2tpv2_encap_conf.ip_tos << + RTE_IPV6_HDR_TC_SHIFT); + action_l2tpv2_encap_data->item_ipv6.hdr.hop_limits = + l2tpv2_encap_conf.ip_ttl; + action_l2tpv2_encap_data->items[2].mask = + &ipv6_mask_tos; + } + } + + if (0xc800 == (l2tpv2_encap_conf.flags_version & 0xcb00)) { + action_l2tpv2_encap_data->item_l2tpv2.hdr.type3.session_id = + l2tpv2_encap_conf.session_id; + } else if (0x4000 == (l2tpv2_encap_conf.flags_version & 0xcb00)) { + action_l2tpv2_encap_data->item_l2tpv2.hdr.type6.session_id = + l2tpv2_encap_conf.session_id; + } + + return 0; +} + +/** Parse l2tpv2 encap action. */ +static int +parse_vc_action_l2tpv2_encap(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + struct rte_flow_action *action; + struct action_l2tpv2_encap_data *action_l2tpv2_encap_data; + int ret; + + ret = parse_vc(ctx, token, str, len, buf, size); + if (ret < 0) + return ret; + /* Nothing else to do if there is no buffer. */ + if (!out) + return ret; + if (!out->args.vc.actions_n) + return -1; + action = &out->args.vc.actions[out->args.vc.actions_n - 1]; + /* Point to selected object. */ + ctx->object = out->args.vc.data; + ctx->objmask = NULL; + action_l2tpv2_encap_data = ctx->object; + parse_setup_l2tpv2_encap_data(action_l2tpv2_encap_data); + action->conf = &action_l2tpv2_encap_data->conf; + return ret; +} + /** Parse l2 encap action. */ static int parse_vc_action_l2_encap(struct context *ctx, const struct token *token, @@ -8333,6 +8718,12 @@ flow_item_default_mask(const struct rte_flow_item *item) case RTE_FLOW_ITEM_TYPE_PFCP: mask = &rte_flow_item_pfcp_mask; break; + case RTE_FLOW_ITEM_TYPE_L2TPV2: + mask = &rte_flow_item_l2tpv2_mask; + break; + case RTE_FLOW_ITEM_TYPE_PPP: + mask = &rte_flow_item_ppp_mask; + break; default: break; } @@ -8432,6 +8823,11 @@ cmd_set_raw_parsed_sample(const struct buffer *in) parse_setup_nvgre_encap_data(&sample_nvgre_encap[idx]); action->conf = &sample_nvgre_encap[idx]; break; + case RTE_FLOW_ACTION_TYPE_L2TPV2_ENCAP: + size = sizeof(struct rte_flow_action_l2tpv2_encap); + parse_setup_l2tpv2_encap_data(&sample_l2tpv2_encap[idx]); + action->conf = &sample_l2tpv2_encap[idx]; + break; default: fprintf(stderr, "Error - Not supported action\n"); return; diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index e9d9db06ce..c744799b46 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -567,6 +567,28 @@ struct nvgre_encap_conf { extern struct nvgre_encap_conf nvgre_encap_conf; +/* L2TPV2 encap/decap parameters. */ +struct l2tpv2_encap_conf { + uint32_t select_ipv4:1; + uint32_t select_vlan:1; + uint32_t select_tos_ttl:1; + rte_be16_t flags_version; + rte_be16_t session_id; + rte_be16_t udp_src; + rte_be16_t udp_dst; + rte_be32_t ipv4_src; + rte_be32_t ipv4_dst; + uint8_t ipv6_src[16]; + uint8_t ipv6_dst[16]; + rte_be16_t vlan_tci; + uint8_t ip_tos; + uint8_t ip_ttl; + uint8_t eth_src[RTE_ETHER_ADDR_LEN]; + uint8_t eth_dst[RTE_ETHER_ADDR_LEN]; +}; + +extern struct l2tpv2_encap_conf l2tpv2_encap_conf; + /* L2 encap parameters. */ struct l2_encap_conf { uint32_t select_ipv4:1;