net/mlx5: fix flow match on GRE key
[dpdk.git] / drivers / net / mlx5 / mlx5_flow_dv.c
index ba88325..467d1ce 100644 (file)
@@ -1746,7 +1746,7 @@ flow_dv_validate_action_push_vlan(uint64_t action_flags,
 {
        const struct rte_flow_action_of_push_vlan *push_vlan = action->conf;
 
-       if (attr->ingress)
+       if (!attr->transfer && attr->ingress)
                return rte_flow_error_set(error, ENOTSUP,
                                          RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
                                          NULL,
@@ -4621,6 +4621,7 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
                                                            error);
                        if (ret < 0)
                                return ret;
+                       item_ipv6_proto = IPPROTO_ICMPV6;
                        last_item = MLX5_FLOW_LAYER_ICMP6;
                        break;
                case RTE_FLOW_ITEM_TYPE_TAG:
@@ -5216,6 +5217,15 @@ flow_dv_translate_item_eth(void *matcher, void *key,
                 rte_be_to_cpu_16(eth_m->type));
        l24_v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, ethertype);
        *(uint16_t *)(l24_v) = eth_m->type & eth_v->type;
+       if (eth_v->type) {
+               /* When ethertype is present set mask for tagged VLAN. */
+               MLX5_SET(fte_match_set_lyr_2_4, headers_m, cvlan_tag, 1);
+               /* Set value for tagged VLAN if ethertype is 802.1Q. */
+               if (eth_v->type == RTE_BE16(RTE_ETHER_TYPE_VLAN) ||
+                   eth_v->type == RTE_BE16(RTE_ETHER_TYPE_QINQ))
+                       MLX5_SET(fte_match_set_lyr_2_4, headers_v, cvlan_tag,
+                                1);
+       }
 }
 
 /**
@@ -5356,6 +5366,7 @@ flow_dv_translate_item_ipv4(void *matcher, void *key,
                 ipv4_m->hdr.next_proto_id);
        MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
                 ipv4_v->hdr.next_proto_id & ipv4_m->hdr.next_proto_id);
+       MLX5_SET(fte_match_set_lyr_2_4, headers_m, cvlan_tag, 1);
 }
 
 /**
@@ -5460,6 +5471,7 @@ flow_dv_translate_item_ipv6(void *matcher, void *key,
                 ipv6_m->hdr.proto);
        MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
                 ipv6_v->hdr.proto & ipv6_m->hdr.proto);
+       MLX5_SET(fte_match_set_lyr_2_4, headers_m, cvlan_tag, 1);
 }
 
 /**
@@ -5582,13 +5594,13 @@ flow_dv_translate_item_gre_key(void *matcher, void *key,
        void *misc_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
        rte_be32_t gre_key_default_mask = RTE_BE32(UINT32_MAX);
 
+       /* GRE K bit must be on and should already be validated */
+       MLX5_SET(fte_match_set_misc, misc_m, gre_k_present, 1);
+       MLX5_SET(fte_match_set_misc, misc_v, gre_k_present, 1);
        if (!key_v)
                return;
        if (!key_m)
                key_m = &gre_key_default_mask;
-       /* GRE K bit must be on and should already be validated */
-       MLX5_SET(fte_match_set_misc, misc_m, gre_k_present, 1);
-       MLX5_SET(fte_match_set_misc, misc_v, gre_k_present, 1);
        MLX5_SET(fte_match_set_misc, misc_m, gre_key_h,
                 rte_be_to_cpu_32(*key_m) >> 8);
        MLX5_SET(fte_match_set_misc, misc_v, gre_key_h,
@@ -6392,6 +6404,12 @@ flow_dv_translate_item_icmp6(void *matcher, void *key,
                return;
        if (!icmp6_m)
                icmp6_m = &rte_flow_item_icmp6_mask;
+       /*
+        * Force flow only to match the non-fragmented IPv6 ICMPv6 packets.
+        * If only the protocol is specified, no need to match the frag.
+        */
+       MLX5_SET(fte_match_set_lyr_2_4, headers_m, frag, 1);
+       MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 0);
        MLX5_SET(fte_match_set_misc3, misc3_m, icmpv6_type, icmp6_m->type);
        MLX5_SET(fte_match_set_misc3, misc3_v, icmpv6_type,
                 icmp6_v->type & icmp6_m->type);
@@ -6439,6 +6457,12 @@ flow_dv_translate_item_icmp(void *matcher, void *key,
                return;
        if (!icmp_m)
                icmp_m = &rte_flow_item_icmp_mask;
+       /*
+        * Force flow only to match the non-fragmented IPv4 ICMP packets.
+        * If only the protocol is specified, no need to match the frag.
+        */
+       MLX5_SET(fte_match_set_lyr_2_4, headers_m, frag, 1);
+       MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag, 0);
        MLX5_SET(fte_match_set_misc3, misc3_m, icmp_type,
                 icmp_m->hdr.icmp_type);
        MLX5_SET(fte_match_set_misc3, misc3_v, icmp_type,
@@ -7609,6 +7633,8 @@ cnt_err:
                case RTE_FLOW_ITEM_TYPE_GRE:
                        flow_dv_translate_item_gre(match_mask, match_value,
                                                   items, tunnel);
+                       matcher.priority = flow->rss.level >= 2 ?
+                                   MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
                        last_item = MLX5_FLOW_LAYER_GRE;
                        break;
                case RTE_FLOW_ITEM_TYPE_GRE_KEY:
@@ -7619,27 +7645,37 @@ cnt_err:
                case RTE_FLOW_ITEM_TYPE_NVGRE:
                        flow_dv_translate_item_nvgre(match_mask, match_value,
                                                     items, tunnel);
+                       matcher.priority = flow->rss.level >= 2 ?
+                                   MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
                        last_item = MLX5_FLOW_LAYER_GRE;
                        break;
                case RTE_FLOW_ITEM_TYPE_VXLAN:
                        flow_dv_translate_item_vxlan(match_mask, match_value,
                                                     items, tunnel);
+                       matcher.priority = flow->rss.level >= 2 ?
+                                   MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
                        last_item = MLX5_FLOW_LAYER_VXLAN;
                        break;
                case RTE_FLOW_ITEM_TYPE_VXLAN_GPE:
                        flow_dv_translate_item_vxlan_gpe(match_mask,
                                                         match_value, items,
                                                         tunnel);
+                       matcher.priority = flow->rss.level >= 2 ?
+                                   MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
                        last_item = MLX5_FLOW_LAYER_VXLAN_GPE;
                        break;
                case RTE_FLOW_ITEM_TYPE_GENEVE:
                        flow_dv_translate_item_geneve(match_mask, match_value,
                                                      items, tunnel);
+                       matcher.priority = flow->rss.level >= 2 ?
+                                   MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
                        last_item = MLX5_FLOW_LAYER_GENEVE;
                        break;
                case RTE_FLOW_ITEM_TYPE_MPLS:
                        flow_dv_translate_item_mpls(match_mask, match_value,
                                                    items, last_item, tunnel);
+                       matcher.priority = flow->rss.level >= 2 ?
+                                   MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
                        last_item = MLX5_FLOW_LAYER_MPLS;
                        break;
                case RTE_FLOW_ITEM_TYPE_MARK:
@@ -7681,6 +7717,8 @@ cnt_err:
                case RTE_FLOW_ITEM_TYPE_GTP:
                        flow_dv_translate_item_gtp(match_mask, match_value,
                                                   items, tunnel);
+                       matcher.priority = flow->rss.level >= 2 ?
+                                   MLX5_PRIORITY_MAP_L2 : MLX5_PRIORITY_MAP_L4;
                        last_item = MLX5_FLOW_LAYER_GTP;
                        break;
                default: