From: Xiaoyu Min Date: Wed, 10 Jul 2019 14:59:45 +0000 (+0800) Subject: net/mlx5: support IP-in-IP tunnel X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=5e33bebdd8d3;p=dpdk.git net/mlx5: support IP-in-IP tunnel 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 --- 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 5ae53c7930..0aeba611e9 100644 --- a/doc/guides/rel_notes/release_19_08.rst +++ b/doc/guides/rel_notes/release_19_08.rst @@ -113,6 +113,7 @@ New Features sequence number and acknowledgment number modification. * Added support for match on ICMP/ICMP6 code and type. * Added support for matching on GRE's key and C,K,S present bits. + * 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 c7e034c815..4ba34dbd36 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 6ccb8a7189..c6c60b5c6b 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -55,6 +55,9 @@ #define MLX5_FLOW_LAYER_ICMP6 (1u << 19) #define MLX5_FLOW_LAYER_GRE_KEY (1u << 20) +#define MLX5_FLOW_LAYER_IPIP (1u << 21) +#define MLX5_FLOW_LAYER_IPV6_ENCAP (1u << 22) + /* Outer Masks. */ #define MLX5_FLOW_LAYER_OUTER_L3 \ (MLX5_FLOW_LAYER_OUTER_L3_IPV4 | MLX5_FLOW_LAYER_OUTER_L3_IPV6) @@ -67,7 +70,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 676f6e515b..3fa624b353 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 @@ -2356,6 +2389,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, @@ -2377,6 +2411,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 @@ -4427,6 +4462,7 @@ cnt_err: 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, @@ -4439,6 +4475,7 @@ cnt_err: 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,