From patchwork Wed Jul 10 14:59:45 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xiaoyu Min X-Patchwork-Id: 56308 X-Patchwork-Delegate: rasland@nvidia.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 1611F231E; Wed, 10 Jul 2019 16:59:52 +0200 (CEST) Received: from git-send-mailer.rdmz.labs.mlnx (unknown [37.142.13.130]) by dpdk.org (Postfix) with ESMTP id 90B4D2AB for ; Wed, 10 Jul 2019 16:59:50 +0200 (CEST) From: Xiaoyu Min To: rasland@mellanox.com, viacheslavo@mellanox.com, Shahaf Shuler , Yongseok Koh , John McNamara , Marko Kovacevic Cc: dev@dpdk.org Date: Wed, 10 Jul 2019 22:59:45 +0800 Message-Id: X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190528020426.18638-1-jackmin@mellanox.com> References: <20190528020426.18638-1-jackmin@mellanox.com> MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v4] net/mlx5: support IP-in-IP tunnel X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 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" Enabled IP-in-IP tunnel type support on DV/DR flow engine. This includes the following combination: - IPv4 over IPv4 - IPv4 over IPv6 - IPv6 over IPv4 - IPv6 over IPv6 MLX5 NIC supports IP-in-IP tunnel via FLEX Parser so need to make sure fw using FLEX Paser profile 0. mlxconfig -d -y set FLEX_PARSER_PROFILE_ENABLE=0 The example testpmd commands would be: - Match on IPv4 over IPv4 packets and do inner RSS: testpmd> flow create 0 ingress pattern eth / ipv4 proto is 0x04 / ipv4 / udp / end actions rss level 2 queues 0 1 2 3 end / end - Match on IPv6 over IPv4 packets and do inner RSS: testpmd> flow create 0 ingress pattern eth / ipv4 proto is 0x29 / ipv6 / udp / end actions rss level 2 queues 0 1 2 3 end / end Signed-off-by: Xiaoyu Min Acked-by: Viacheslav Ovsiienko --- v2: * updated release note v3: * rebased on 19.08-rc1 v4: * add example testpmd commands in commit log --- doc/guides/nics/mlx5.rst | 15 ++++++++++- doc/guides/rel_notes/release_19_08.rst | 1 + drivers/net/mlx5/mlx5_flow.c | 35 ++++++++++++++++++++++++ drivers/net/mlx5/mlx5_flow.h | 6 ++++- drivers/net/mlx5/mlx5_flow_dv.c | 37 ++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 2 deletions(-) diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst index 20cbba7ace..16aa390380 100644 --- a/doc/guides/nics/mlx5.rst +++ b/doc/guides/nics/mlx5.rst @@ -76,7 +76,7 @@ Features - RX interrupts. - Statistics query including Basic, Extended and per queue. - Rx HW timestamp. -- Tunnel types: VXLAN, L3 VXLAN, VXLAN-GPE, GRE, MPLSoGRE, MPLSoUDP. +- Tunnel types: VXLAN, L3 VXLAN, VXLAN-GPE, GRE, MPLSoGRE, MPLSoUDP, IP-in-IP. - Tunnel HW offloads: packet type, inner/outer RSS, IP and UDP checksum verification. - NIC HW offloads: encapsulation (vxlan, gre, mplsoudp, mplsogre), NAT, routing, TTL increment/decrement, count, drop, mark. For details please see :ref:`Supported hardware offloads using rte_flow API`. @@ -540,6 +540,19 @@ Firmware configuration mlxconfig -d query | grep FLEX_PARSER_PROFILE_ENABLE FLEX_PARSER_PROFILE_ENABLE 2 +- IP-in-IP tunnel enable + + .. code-block:: console + + mlxconfig -d set FLEX_PARSER_PROFILE_ENABLE=0 + + Verify configurations are set: + + .. code-block:: console + + mlxconfig -d query | grep FLEX_PARSER_PROFILE_ENABLE + FLEX_PARSER_PROFILE_ENABLE 0 + Prerequisites ------------- diff --git a/doc/guides/rel_notes/release_19_08.rst b/doc/guides/rel_notes/release_19_08.rst index 27d5915bed..a9ec6adb69 100644 --- a/doc/guides/rel_notes/release_19_08.rst +++ b/doc/guides/rel_notes/release_19_08.rst @@ -112,6 +112,7 @@ New Features * Updated the packet header modification feature. Added support of TCP header sequence number and acknowledgment number modification. * Added support for match on ICMP/ICMP6 code and type. + * Added support for IP-in-IP tunnel. * **Updated Solarflare network PMD.** diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index 534cd9338e..005a1a69a7 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -1282,6 +1282,7 @@ mlx5_flow_validate_item_ipv4(const struct rte_flow_item *item, struct rte_flow_error *error) { const struct rte_flow_item_ipv4 *mask = item->mask; + const struct rte_flow_item_ipv4 *spec = item->spec; const struct rte_flow_item_ipv4 nic_mask = { .hdr = { .src_addr = RTE_BE32(0xffffffff), @@ -1296,7 +1297,24 @@ mlx5_flow_validate_item_ipv4(const struct rte_flow_item *item, const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 : MLX5_FLOW_LAYER_OUTER_L4; int ret; + uint8_t next_proto = 0xFF; + if (item_flags & MLX5_FLOW_LAYER_IPIP) { + if (mask && spec) + next_proto = mask->hdr.next_proto_id & + spec->hdr.next_proto_id; + if (next_proto == IPPROTO_IPIP || next_proto == IPPROTO_IPV6) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "multiple tunnel " + "not supported"); + } + if (item_flags & MLX5_FLOW_LAYER_IPV6_ENCAP) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "wrong tunnel type - IPv6 specified " + "but IPv4 item provided"); if (item_flags & l3m) return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item, @@ -1346,6 +1364,7 @@ mlx5_flow_validate_item_ipv6(const struct rte_flow_item *item, struct rte_flow_error *error) { const struct rte_flow_item_ipv6 *mask = item->mask; + const struct rte_flow_item_ipv6 *spec = item->spec; const struct rte_flow_item_ipv6 nic_mask = { .hdr = { .src_addr = @@ -1365,7 +1384,23 @@ mlx5_flow_validate_item_ipv6(const struct rte_flow_item *item, const uint64_t l4m = tunnel ? MLX5_FLOW_LAYER_INNER_L4 : MLX5_FLOW_LAYER_OUTER_L4; int ret; + uint8_t next_proto = 0xFF; + if (item_flags & MLX5_FLOW_LAYER_IPV6_ENCAP) { + if (mask && spec) + next_proto = mask->hdr.proto & spec->hdr.proto; + if (next_proto == IPPROTO_IPIP || next_proto == IPPROTO_IPV6) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, + item, + "multiple tunnel " + "not supported"); + } + if (item_flags & MLX5_FLOW_LAYER_IPIP) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "wrong tunnel type - IPv4 specified " + "but IPv6 item provided"); if (item_flags & l3m) return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item, diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index 3d7fcf706e..ef430d6d44 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -54,6 +54,9 @@ #define MLX5_FLOW_LAYER_ICMP (1u << 18) #define MLX5_FLOW_LAYER_ICMP6 (1u << 19) +#define MLX5_FLOW_LAYER_IPIP (1u << 20) +#define MLX5_FLOW_LAYER_IPV6_ENCAP (1u << 21) + /* Outer Masks. */ #define MLX5_FLOW_LAYER_OUTER_L3 \ (MLX5_FLOW_LAYER_OUTER_L3_IPV4 | MLX5_FLOW_LAYER_OUTER_L3_IPV6) @@ -66,7 +69,8 @@ /* Tunnel Masks. */ #define MLX5_FLOW_LAYER_TUNNEL \ (MLX5_FLOW_LAYER_VXLAN | MLX5_FLOW_LAYER_VXLAN_GPE | \ - MLX5_FLOW_LAYER_GRE | MLX5_FLOW_LAYER_MPLS) + MLX5_FLOW_LAYER_GRE | MLX5_FLOW_LAYER_MPLS | \ + MLX5_FLOW_LAYER_IPIP | MLX5_FLOW_LAYER_IPV6_ENCAP) /* Inner Masks. */ #define MLX5_FLOW_LAYER_INNER_L3 \ diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index 9cc09e73c9..54c1b9f2e1 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -141,6 +141,39 @@ struct field_modify_info modify_tcp[] = { {0, 0, 0}, }; +static void +mlx5_flow_tunnel_ip_check(const struct rte_flow_item *item, uint64_t *flags) +{ + uint8_t next_protocol = 0xFF; + + if (item->mask != NULL) { + switch (item->type) { + case RTE_FLOW_ITEM_TYPE_IPV4: + next_protocol = + ((const struct rte_flow_item_ipv4 *) + (item->spec))->hdr.next_proto_id; + next_protocol &= + ((const struct rte_flow_item_ipv4 *) + (item->mask))->hdr.next_proto_id; + break; + case RTE_FLOW_ITEM_TYPE_IPV6: + next_protocol = + ((const struct rte_flow_item_ipv6 *) + (item->spec))->hdr.proto; + next_protocol &= + ((const struct rte_flow_item_ipv6 *) + (item->mask))->hdr.proto; + break; + default: + break; + } + } + if (next_protocol == IPPROTO_IPIP) + *flags |= MLX5_FLOW_LAYER_IPIP; + if (next_protocol == IPPROTO_IPV6) + *flags |= MLX5_FLOW_LAYER_IPV6_ENCAP; +} + /** * Acquire the synchronizing object to protect multithreaded access * to shared dv context. Lock occurs only if context is actually @@ -2355,6 +2388,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, /* Reset for inner layer. */ next_protocol = 0xff; } + mlx5_flow_tunnel_ip_check(items, &last_item); break; case RTE_FLOW_ITEM_TYPE_IPV6: ret = mlx5_flow_validate_item_ipv6(items, item_flags, @@ -2376,6 +2410,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, /* Reset for inner layer. */ next_protocol = 0xff; } + mlx5_flow_tunnel_ip_check(items, &last_item); break; case RTE_FLOW_ITEM_TYPE_TCP: ret = mlx5_flow_validate_item_tcp @@ -4348,6 +4383,7 @@ flow_dv_translate(struct rte_eth_dev *dev, MLX5_IPV4_IBV_RX_HASH); last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 : MLX5_FLOW_LAYER_OUTER_L3_IPV4; + mlx5_flow_tunnel_ip_check(items, &last_item); break; case RTE_FLOW_ITEM_TYPE_IPV6: flow_dv_translate_item_ipv6(match_mask, match_value, @@ -4360,6 +4396,7 @@ flow_dv_translate(struct rte_eth_dev *dev, MLX5_IPV6_IBV_RX_HASH); last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 : MLX5_FLOW_LAYER_OUTER_L3_IPV6; + mlx5_flow_tunnel_ip_check(items, &last_item); break; case RTE_FLOW_ITEM_TYPE_TCP: flow_dv_translate_item_tcp(match_mask, match_value,