From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 4E74DA0353 for ; Tue, 5 Nov 2019 08:51:32 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 2774B374C; Tue, 5 Nov 2019 08:51:32 +0100 (CET) Received: from git-send-mailer.rdmz.labs.mlnx (unknown [37.142.13.130]) by dpdk.org (Postfix) with ESMTP id ECF3529AC; Tue, 5 Nov 2019 08:51:29 +0100 (CET) From: Xiaoyu Min To: Matan Azrad , Shahaf Shuler , Viacheslav Ovsiienko Cc: dev@dpdk.org, stable@dpdk.org, Ori Kam Date: Tue, 5 Nov 2019 09:51:27 +0200 Message-Id: <7530e05d3d2da15a9876825a1a70ffdf97769fa5.1572939962.git.jackmin@mellanox.com> X-Mailer: git-send-email 2.21.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [dpdk-stable] [PATCH] net/mlx5: improve flow item IP validation X-BeenThere: stable@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches for DPDK stable branches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: stable-bounces@dpdk.org Sender: "stable" Currently PMD doesn't check whether the user specified ethernet type is conflicting with the followed IPv4/IPv6 items, which leads to HW refuse to create rule, for example: ... pattern eth type is 0x86dd / ipv4 / end ... ethernet type is IPv6 but IPv4 is following, this should be validated as failure and report corresponding error in detail. Fixes: 23c1d42c7138 ("net/mlx5: split flow validation to dedicated function") Cc: stable@dpdk.org Signed-off-by: Xiaoyu Min Acked-by: Ori Kam --- drivers/net/mlx5/mlx5_flow.c | 22 +++++++++++++++++++++ drivers/net/mlx5/mlx5_flow.h | 4 ++++ drivers/net/mlx5/mlx5_flow_dv.c | 31 ++++++++++++++++++++++++++++-- drivers/net/mlx5/mlx5_flow_verbs.c | 31 ++++++++++++++++++++++++++++-- 4 files changed, 84 insertions(+), 4 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index b4b08f4c6c..54f4cfe04b 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -1403,6 +1403,8 @@ mlx5_flow_validate_item_vlan(const struct rte_flow_item *item, int mlx5_flow_validate_item_ipv4(const struct rte_flow_item *item, uint64_t item_flags, + uint64_t last_item, + uint16_t ether_type, const struct rte_flow_item_ipv4 *acc_mask, struct rte_flow_error *error) { @@ -1423,7 +1425,16 @@ mlx5_flow_validate_item_ipv4(const struct rte_flow_item *item, MLX5_FLOW_LAYER_OUTER_L4; int ret; uint8_t next_proto = 0xFF; + const uint64_t l2_vlan = (MLX5_FLOW_LAYER_L2 | + MLX5_FLOW_LAYER_OUTER_VLAN | + MLX5_FLOW_LAYER_INNER_VLAN); + if ((last_item & l2_vlan) && ether_type && + ether_type != RTE_ETHER_TYPE_IPV4) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "IPv4 cannot follow L2/VLAN layer " + "which ether type is not IPv4"); if (item_flags & MLX5_FLOW_LAYER_IPIP) { if (mask && spec) next_proto = mask->hdr.next_proto_id & @@ -1494,6 +1505,8 @@ mlx5_flow_validate_item_ipv4(const struct rte_flow_item *item, int mlx5_flow_validate_item_ipv6(const struct rte_flow_item *item, uint64_t item_flags, + uint64_t last_item, + uint16_t ether_type, const struct rte_flow_item_ipv6 *acc_mask, struct rte_flow_error *error) { @@ -1519,7 +1532,16 @@ mlx5_flow_validate_item_ipv6(const struct rte_flow_item *item, MLX5_FLOW_LAYER_OUTER_L4; int ret; uint8_t next_proto = 0xFF; + const uint64_t l2_vlan = (MLX5_FLOW_LAYER_L2 | + MLX5_FLOW_LAYER_OUTER_VLAN | + MLX5_FLOW_LAYER_INNER_VLAN); + if ((last_item & l2_vlan) && ether_type && + ether_type != RTE_ETHER_TYPE_IPV6) + return rte_flow_error_set(error, EINVAL, + RTE_FLOW_ERROR_TYPE_ITEM, item, + "IPv6 cannot follow L2/VLAN layer " + "which ether type is not IPv6"); if (item_flags & MLX5_FLOW_LAYER_IPV6_ENCAP) { if (mask && spec) next_proto = mask->hdr.proto & spec->hdr.proto; diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index 7559810d01..d33d856ad2 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -600,10 +600,14 @@ int mlx5_flow_validate_item_gre_key(const struct rte_flow_item *item, struct rte_flow_error *error); int mlx5_flow_validate_item_ipv4(const struct rte_flow_item *item, uint64_t item_flags, + uint64_t last_item, + uint16_t ether_type, const struct rte_flow_item_ipv4 *acc_mask, struct rte_flow_error *error); int mlx5_flow_validate_item_ipv6(const struct rte_flow_item *item, uint64_t item_flags, + uint64_t last_item, + uint16_t ether_type, const struct rte_flow_item_ipv6 *acc_mask, struct rte_flow_error *error); int mlx5_flow_validate_item_mpls(struct rte_eth_dev *dev, diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index 4be059ded5..8e1fa53699 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -3383,6 +3383,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, uint64_t item_flags = 0; uint64_t last_item = 0; uint8_t next_protocol = 0xff; + uint16_t ether_type = 0; int actions_n = 0; const struct rte_flow_item *gre_item = NULL; struct rte_flow_item_tcp nic_tcp_mask = { @@ -3419,6 +3420,17 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, return ret; last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 : MLX5_FLOW_LAYER_OUTER_L2; + if (items->mask != NULL && items->spec != NULL) { + ether_type = + ((const struct rte_flow_item_eth *) + items->spec)->type; + ether_type &= + ((const struct rte_flow_item_eth *) + items->mask)->type; + ether_type = rte_be_to_cpu_16(ether_type); + } else { + ether_type = 0; + } break; case RTE_FLOW_ITEM_TYPE_VLAN: ret = mlx5_flow_validate_item_vlan(items, item_flags, @@ -3427,12 +3439,25 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, return ret; last_item = tunnel ? MLX5_FLOW_LAYER_INNER_VLAN : MLX5_FLOW_LAYER_OUTER_VLAN; + if (items->mask != NULL && items->spec != NULL) { + ether_type = + ((const struct rte_flow_item_vlan *) + items->spec)->inner_type; + ether_type &= + ((const struct rte_flow_item_vlan *) + items->mask)->inner_type; + ether_type = rte_be_to_cpu_16(ether_type); + } else { + ether_type = 0; + } break; case RTE_FLOW_ITEM_TYPE_IPV4: mlx5_flow_tunnel_ip_check(items, next_protocol, &item_flags, &tunnel); ret = mlx5_flow_validate_item_ipv4(items, item_flags, - NULL, error); + last_item, + ether_type, NULL, + error); if (ret < 0) return ret; last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 : @@ -3455,7 +3480,9 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, mlx5_flow_tunnel_ip_check(items, next_protocol, &item_flags, &tunnel); ret = mlx5_flow_validate_item_ipv6(items, item_flags, - NULL, error); + last_item, + ether_type, NULL, + error); if (ret < 0) return ret; last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 : diff --git a/drivers/net/mlx5/mlx5_flow_verbs.c b/drivers/net/mlx5/mlx5_flow_verbs.c index fd27f6c3de..147436d7b3 100644 --- a/drivers/net/mlx5/mlx5_flow_verbs.c +++ b/drivers/net/mlx5/mlx5_flow_verbs.c @@ -1037,6 +1037,7 @@ flow_verbs_validate(struct rte_eth_dev *dev, uint64_t item_flags = 0; uint64_t last_item = 0; uint8_t next_protocol = 0xff; + uint16_t ether_type = 0; if (items == NULL) return -1; @@ -1057,6 +1058,17 @@ flow_verbs_validate(struct rte_eth_dev *dev, return ret; last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L2 : MLX5_FLOW_LAYER_OUTER_L2; + if (items->mask != NULL && items->spec != NULL) { + ether_type = + ((const struct rte_flow_item_eth *) + items->spec)->type; + ether_type &= + ((const struct rte_flow_item_eth *) + items->mask)->type; + ether_type = rte_be_to_cpu_16(ether_type); + } else { + ether_type = 0; + } break; case RTE_FLOW_ITEM_TYPE_VLAN: ret = mlx5_flow_validate_item_vlan(items, item_flags, @@ -1067,10 +1079,23 @@ flow_verbs_validate(struct rte_eth_dev *dev, MLX5_FLOW_LAYER_INNER_VLAN) : (MLX5_FLOW_LAYER_OUTER_L2 | MLX5_FLOW_LAYER_OUTER_VLAN); + if (items->mask != NULL && items->spec != NULL) { + ether_type = + ((const struct rte_flow_item_vlan *) + items->spec)->inner_type; + ether_type &= + ((const struct rte_flow_item_vlan *) + items->mask)->inner_type; + ether_type = rte_be_to_cpu_16(ether_type); + } else { + ether_type = 0; + } break; case RTE_FLOW_ITEM_TYPE_IPV4: ret = mlx5_flow_validate_item_ipv4(items, item_flags, - NULL, error); + last_item, + ether_type, NULL, + error); if (ret < 0) return ret; last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV4 : @@ -1091,7 +1116,9 @@ flow_verbs_validate(struct rte_eth_dev *dev, break; case RTE_FLOW_ITEM_TYPE_IPV6: ret = mlx5_flow_validate_item_ipv6(items, item_flags, - NULL, error); + last_item, + ether_type, NULL, + error); if (ret < 0) return ret; last_item = tunnel ? MLX5_FLOW_LAYER_INNER_L3_IPV6 : -- 2.24.0.rc0.3.g12a4aeaad8