net/mlx5: support ESP SPI match and RSS hash
[dpdk.git] / drivers / net / mlx5 / mlx5_flow_dv.c
index f9c5620..9a0102a 100644 (file)
@@ -6956,6 +6956,14 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr,
                switch (type) {
                case RTE_FLOW_ITEM_TYPE_VOID:
                        break;
+               case RTE_FLOW_ITEM_TYPE_ESP:
+                       ret = mlx5_flow_validate_item_esp(items, item_flags,
+                                                         next_protocol,
+                                                         error);
+                       if (ret < 0)
+                               return ret;
+                       last_item = MLX5_FLOW_ITEM_ESP;
+                       break;
                case RTE_FLOW_ITEM_TYPE_PORT_ID:
                        ret = flow_dv_validate_item_port_id
                                        (dev, items, attr, item_flags, error);
@@ -8730,6 +8738,58 @@ flow_dv_translate_item_tcp(void *matcher, void *key,
                 (tcp_v->hdr.tcp_flags & tcp_m->hdr.tcp_flags));
 }
 
+/**
+ * Add ESP item to matcher and to the value.
+ *
+ * @param[in, out] matcher
+ *   Flow matcher.
+ * @param[in, out] key
+ *   Flow matcher value.
+ * @param[in] item
+ *   Flow pattern to translate.
+ * @param[in] inner
+ *   Item is inner pattern.
+ */
+static void
+flow_dv_translate_item_esp(void *matcher, void *key,
+                          const struct rte_flow_item *item,
+                          int inner)
+{
+       const struct rte_flow_item_esp *esp_m = item->mask;
+       const struct rte_flow_item_esp *esp_v = item->spec;
+       void *headers_m;
+       void *headers_v;
+       char *spi_m;
+       char *spi_v;
+
+       if (inner) {
+               headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+                                        inner_headers);
+               headers_v = MLX5_ADDR_OF(fte_match_param, key, inner_headers);
+       } else {
+               headers_m = MLX5_ADDR_OF(fte_match_param, matcher,
+                                        outer_headers);
+               headers_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
+       }
+       MLX5_SET(fte_match_set_lyr_2_4, headers_m, ip_protocol, 0xff);
+       MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol, IPPROTO_ESP);
+       if (!esp_v)
+               return;
+       if (!esp_m)
+               esp_m = &rte_flow_item_esp_mask;
+       headers_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters);
+       headers_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters);
+       if (inner) {
+               spi_m = MLX5_ADDR_OF(fte_match_set_misc, headers_m, inner_esp_spi);
+               spi_v = MLX5_ADDR_OF(fte_match_set_misc, headers_v, inner_esp_spi);
+       } else {
+               spi_m = MLX5_ADDR_OF(fte_match_set_misc, headers_m, outer_esp_spi);
+               spi_v = MLX5_ADDR_OF(fte_match_set_misc, headers_v, outer_esp_spi);
+       }
+       *(uint32_t *)spi_m = esp_m->hdr.spi;
+       *(uint32_t *)spi_v = esp_m->hdr.spi & esp_v->hdr.spi;
+}
+
 /**
  * Add UDP item to matcher and to the value.
  *
@@ -11189,12 +11249,18 @@ flow_dv_hashfields_set(uint64_t item_flags,
                                fields |= MLX5_IPV6_IBV_RX_HASH;
                }
        }
-       if (fields == 0)
+       if (items & MLX5_FLOW_ITEM_ESP) {
+               if (rss_types & RTE_ETH_RSS_ESP)
+                       fields |= IBV_RX_HASH_IPSEC_SPI;
+       }
+       if ((fields & ~IBV_RX_HASH_IPSEC_SPI) == 0) {
+               *hash_fields = fields;
                /*
                 * There is no match between the RSS types and the
                 * L3 protocol (IPv4/IPv6) defined in the flow rule.
                 */
                return;
+       }
        if ((rss_inner && (items & MLX5_FLOW_LAYER_INNER_L4_UDP)) ||
            (!rss_inner && (items & MLX5_FLOW_LAYER_OUTER_L4_UDP)) ||
            !items) {
@@ -13539,6 +13605,11 @@ flow_dv_translate(struct rte_eth_dev *dev,
                                                  RTE_FLOW_ERROR_TYPE_ITEM,
                                                  NULL, "item not supported");
                switch (item_type) {
+               case RTE_FLOW_ITEM_TYPE_ESP:
+                       flow_dv_translate_item_esp(match_mask, match_value,
+                                                  items, tunnel);
+                       last_item = MLX5_FLOW_ITEM_ESP;
+                       break;
                case RTE_FLOW_ITEM_TYPE_PORT_ID:
                        flow_dv_translate_item_port_id
                                (dev, match_mask, match_value, items, attr);
@@ -14008,6 +14079,15 @@ __flow_dv_action_rss_hrxq_set(struct mlx5_shared_action_rss *action,
        case MLX5_RSS_HASH_NONE:
                hrxqs[6] = hrxq_idx;
                return 0;
+       case MLX5_RSS_HASH_IPV4_ESP:
+               hrxqs[7] = hrxq_idx;
+               return 0;
+       case MLX5_RSS_HASH_IPV6_ESP:
+               hrxqs[8] = hrxq_idx;
+               return 0;
+       case MLX5_RSS_HASH_ESP_SPI:
+               hrxqs[9] = hrxq_idx;
+               return 0;
        default:
                return -1;
        }
@@ -14077,6 +14157,12 @@ flow_dv_action_rss_hrxq_lookup(struct rte_eth_dev *dev, uint32_t idx,
                return hrxqs[5];
        case MLX5_RSS_HASH_NONE:
                return hrxqs[6];
+       case MLX5_RSS_HASH_IPV4_ESP:
+               return hrxqs[7];
+       case MLX5_RSS_HASH_IPV6_ESP:
+               return hrxqs[8];
+       case MLX5_RSS_HASH_ESP_SPI:
+               return hrxqs[9];
        default:
                return 0;
        }